首先看一下界面
如图所示,通过勾选多选框实现选中,点击批量下载会将数据以Excel的格式批量下载到本地
关于勾选之后是传id数组还是传整个勾选的对象数组,先说结论:
应该传的是id数组而不是对象数组 原因如下:
1. 我们为什么不传id?因为我们不想查询数据库。
2. 但是不查询数据库说明我们所需要打印的数据在前端界面已经展示
完全了,
3. 界面展示完全的话。我们可以通过直接通过前端把数据导出成
Excel表格下载到本地
4. 故 我们一般选择通过id数组传递数据
结论是一回事,但是我两种都写了,传递id数组的方式比较简单。
emmmmmm,选这种的和我一样都是狼灭
直接开始思路:
应该传Json字符串
[{“name”:“csq”,“sex”:“man”},
{“name”:“lll”,“sex”:“woman”}]
java.lang.IllegalArgumentException:Invalid character found
in the request target. The valid characters are defined in
RFC 7230 and RFC 3986
翻译:非法数据异常:发现无效字符,有效的字符在RFC 7230和RFC 3986中定义
出现这个错误的原因是:我们在前后台交互的时候使用json格式的字段串参数,其中含有“{}”“[]”这些特舒符号,在高版本的tomcat(已知8版本以上报错,7貌似也报)中含有这些字符的请求会被拦截。
解决办法:
@Configuration
public class TomcatConfig {
@Bean
public TomcatServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers((Connector connector) -> {
connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");
connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
});
return factory;
}
}
我的前端使用的是layui
<div class="layui-fluid">
<div class="layui-row">
div>
<button type="button" class="layui-btn" id="uploads">
<i class="layui-icon">i>批量上传
button>
<button type="button" class="layui-btn" id="download">
<i class="layui-icon">i>批量下载
button>
<table id="guruTable" class="layui-table-cell" lay-filter="test">table>
div>
div>
<script src="layui/layui.js"></script>
<script type="text/javascript" src="layui/js/jquery-1.9.js"></script>
<script>
layui.use(['table','layer','form','laydate','upload','tree'], function(){
var table = layui.table;
var layer = layui.layer;
var form = layui.form;
var upload = layui.upload;
//批量下载按钮的点击事件
$("#download").click(function () {
var checkStatus = table.checkStatus('guruTable'),
data = checkStatus.data,
gurus = [];
console.log(checkStatus.data) ;//获取选中行的数据
console.log(checkStatus.data.length) ;//获取选中行数量,可作为是否有选中行的条件
console.log(checkStatus.isAll ) ;//表格是否全选
/*
声明前缀和后缀
*/
var prefix;
var suffix;
console.log(checkStatus.data.length-1);
// console.log(checkStatus.data.size-1); 这种不行,前端数据一般都是数组类型的,长度要用length 否则结果是undefine
/*
要拼接成json类型的数据,第一个数据前面加"[",最后一个数组后面加"]"
*/
checkStatus.data.forEach(function(n,i){
if (i === 0){
prefix = "[";
suffix = "";
} else if (i === checkStatus.data.length-1) {
suffix = "]";
prefix = "";
} else {
prefix = "";
suffix = "";
}
var str = prefix+"{'guruId':'"+n.guruId+"','guruName':'"+n.guruName+"','guruImage':'"+n.guruImage+"','guruNickname':'"+n.guruNickname+"','guruStatus':'"+n.guruStatus+"'}"+suffix;
console.log("str"+i+" = "+str);
gurus.push(str);
});
console.log("gurus = "+gurus);
window.location.href = "${pageContext.request.contextPath}/guru/outputGurus?gurus="+gurus;
});
/执行文件上传实例
var uploadInst = upload.render({
elem: '#uploads' //绑定元素
,url: 'guru/importGurus' //上传接口
,accept:'file'
,done: function(res){
alert("上传成功");
table.reload("demo");
layui.close(uploadInst);
}
,error: function(){
//请求异常回调
}
});
//----------------------- 表格组件开始 -------------------------------------
table.render({
elem: '#guruTable'
,size:'lg'
,height: 300
,url: 'guru/selectAll' //数据接口
,page: true //开启分页
,limits:[4,8,10]
,limit:4
,cols: [[ //表头
{
type:'checkbox', fixed: 'left'},
{
field: 'guruId', title: '上师编号', fixed: 'left'}
,{
field: 'guruName', title: '上师姓名'}
,{
field: 'guruImage', title: '上师图片', sort: true, templet:function (d) {
return "
";
}}
,{
field: 'guruNickname', title: '上师法号'}
,{
field: 'guruStatus', title: '上师状态', templet:function (d) {
if (d.guruStatus === 0){
return "正常";
} else {
return "已冻结";
}
}}
]]
});
//----------------------- 表格组件结束 -------------------------------------
</script>
@Configuration
public class TomcatConfig {
@Bean
public TomcatServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers((Connector connector) -> {
connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");
connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
});
return factory;
}
}
/*
批量下载的代码
*/
@RequestMapping("outputGurus")
public void outputGurus(@RequestParam(value = "gurus") String gurus, HttpServletResponse response) throws IOException {
/*
ArrayList list = JSONUtil.toBean(gurus, ArrayList.class);
这种转换是不行的,因为gurus是json数组,我们需要用json数组对象接收
json数组转成字符串需要用JSONArray接收
*/
JSONArray objects = new JSONArray(gurus);
//将json数组转成你想要的数据类型,.to就完事了。
List<Guru> list = objects.toList(Guru.class);
//不放心就先打印一下看看拿到了没
list.forEach(System.out::println);
// 处理Excel中的图片路径。数据库中存储的是图片名字,需要加上前缀
list.stream().forEach(guru -> {
guru.setGuruImage("http://localhost:8989/cmfz/img/"+guru.getGuruImage());
});
/**
easypoi 操作Excel导出导入
*/
ExportParams exportParams = new ExportParams("所有上师数据", "guru");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Guru.class, list);
String s = "上师数据"+System.currentTimeMillis()+".xlsx";
//解决H5请求接口的跨域问题
//response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("content-disposition","attachment;fileName=" + URLEncoder.encode(s,"utf-8"));
response.setContentType("application/vnd.ms-excel");
//通过文件对象写出
workbook.write(response.getOutputStream());
}
//上传代码
@RequestMapping("importGurus")
public Map piliang(MultipartFile file) throws Exception {
Map<String,Object> map = new HashMap<>(4);
//将file对象给poi处理
//通过file对象获取到输入流
InputStream inputStream = file.getInputStream();
// 2. 通过poi处理流
ImportParams importParams = new ImportParams();
/**
* setTitleRows(1);设置标题所占的行数
* setHeadRows(1);设置表头所占的行数
*/
importParams.setTitleRows(1);
importParams.setHeadRows(1);
List<Guru> list = ExcelImportUtil.importExcel(inputStream, Guru.class, importParams);
list.stream().forEach(guru -> {
String removePrefix = StrUtil.removePrefix(guru.getGuruImage(), "F:\\IdeaProjects\\last-program\\cmfzdemo\\src\\main\\webapp\\img\\");
guru.setGuruImage(removePrefix);
System.out.println(guru);
});
guruService.saveBatch(list);
map.put("code",0);
map.put("msg","success");
return map;
}
累了,写博客好累,有空再写传id数组的写法。。。
准备截界面的图时突然出现的报错ヽ(ー_ー)ノ
口头翻译了一下 大概意思是缓存读取错误…200
重启springboot,表格加载出来了,但是里面的图片没有出来
ヽ(。_°)ノ 吐了 同样是缓存读取失败,状态码还不一样
原因:Chrome自己的问题,可以选择两种修改方式,我推荐第一种
解决办法1:手动强制刷新Chrome,使Chrome不从缓存中读取数据
Windows和Linux操作系统: Shift+F5 或 Ctrl+Shift+R
Mac OS: Cmd+Shft+R
解决办法2:别问,我也不知道这从哪配的
1. chrome://flags/#enable-simple-cache-backend
2. default -> enable
成功,结果如页面最上面展示
后端用了二进制流来实现,而ajax不支持流形式,可以选择使用window.location.href 或者 表单提交
一、解决springboot项目请求出现非法字符问题
二、json数组如何转换成string类型
三、spring MVC 前台传数组类型,后台用list类型接收也是可以的
四、前端页面传来数组,后台用对象集合list接收数据的写法
五、Springboot 下载文件