vue.js前端,Java后端,如何导入excel文件,并且解析,本文给了前后端代码的实现,以及完美实践OK之后的分享。
前端主要用了element-ui的upload组件。
关于这个组件的官方文档很少:http://element-cn.eleme.io/#/zh-CN/component/upload ,也没仔细给个完整的demo,所以踩完坑写个完整的博客。
选取文件
批量导入
只能上传excel文件
关于每个字段的意思:
uploadUrl() 是后台接口(接受上传的文件并做后端的逻辑处理)
!!!注意:uploadUrl方法中,直接return的是你的后端URL接口,可以是相对路径,也可以是绝对路径
取相对路径的时候,会自动加上请求所在页面的前缀htpp://XXX作为请求URL的前缀,如果这样拼接的不对,自己就加上绝对路径:http://localhost:8080/XX 这样类似的URL
upLoadData是上传文件时要上传的额外参数,也可以不写,将参数直接带在URL请求中,见下面的demo
形似: url + "?businessName=" + this.businessName
uploadError是上传文件失败时的回掉函数,uploadSuccess是文件上传成功时的回掉函数,
beforeAvatarUpload是在上传文件之前调用的函数,可以在这里进行文件类型的判断,对上传格式及大小作限制
:auto-upload="false"是停止文件自动上传模式
name="excelFile"这里是将导入的EXCEL文件命名,并传给后端,所以后端接口的入参也要是这个名字,下面会贴代码。
:file-list="fileList" 显示已上传的文件列表,效果见下图3
是为了实现将选取文件和上传分开,效果如下:
关于上传多个文件
首先是设置是否可以同时选中多个文件上传,这个也是的属性,添加multiple即可。另外el-upload组件提供了:limit属性来设置最多可以上传的文件数量,超出此数量后选择的文件是不会被上传的。:on-exceed绑定的方法则是处理超出数量后的动作。(但一般单个文件批量导入够用了)代码如下:
上面每个方法对应的实现:
methods: {
uploadUrl: function() {
return (
"/fanxing/import/batchInsertShops" +
"?businessName=" +
this.businessName +
"&businessStatus=" +
this.businessStatus +
"&businessType=" +
this.businessType
);
},
uploadSuccess(response, file, fileList) {
if (response.status) {
alert("文件导入成功");
} else {
alert("文件导入失败");
}
},
uploadFalse(response, file, fileList) {
alert("文件上传失败!");
},
// 上传前对文件的大小的判断
beforeAvatarUpload(file) {
const extension = file.name.split(".")[1] === "xls";
const extension2 = file.name.split(".")[1] === "xlsx";
const extension3 = file.name.split(".")[1] === "doc";
const extension4 = file.name.split(".")[1] === "docx";
const isLt2M = file.size / 1024 / 1024 < 10;
if (!extension && !extension2 && !extension3 && !extension4) {
alert("上传模板只能是 xls、xlsx、doc、docx 格式!");
}
if (!isLt2M) {
console.log("上传模板大小不能超过 10MB!");
}
return extension || extension2 || extension3 || (extension4 && isLt2M);
},
submitUpload() {
if (this.businessType != null) {
//触发组件的action
this.$refs.upload.submit();
}
if (this.businessType == null) {
this.businessType = "businessType不能为空";
}
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
if (file.response.status) {
alert("此文件导入成功");
} else {
alert("此文件导入失败");
}
}
}
贴上效果图:
@Controller
@RequestMapping(value = "/fanxing/import")
public class ImportController {
@Resource
ImportDataService importDataService;
@RequestMapping(value = "/batchInsertShops", method = RequestMethod.POST)
@ResponseBody
public ResultData batchInsert(@RequestParam("excelFile") MultipartFile excelFile,
@RequestParam(value = "businessName", required = true ) String businessName,
@RequestParam(value = "businessStatus", required = true) Integer businessStatus,
@RequestParam(value = "businessType", required = true) Integer businessType) throws IOException {
String name = excelFile.getOriginalFilename();
if (name.length() < 6 || !name.substring(name.length() - 5).equals(".xlsx")) {
return ResultDataBuilder.failWithNull("文件格式错误", ResultCode.FILE_FORMAT_ERROR.getCode());
}
//TODO 业务逻辑,通过excelFile.getInputStream(),处理Excel文件
ExcelUtils.excelToShopIdList(excelFile.getInputStream());
}
}
package com.dianping.fanxing.system.admin.web.util;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ExcelUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtils.class);
public static List excelToShopIdList(InputStream inputStream) {
List list = new ArrayList<>();
Workbook workbook = null;
try {
workbook = WorkbookFactory.create(inputStream);
inputStream.close();
//工作表对象
Sheet sheet = workbook.getSheetAt(0);
//总行数
int rowLength = sheet.getLastRowNum() + 1;
//工作表的列
Row row = sheet.getRow(0);
//总列数
int colLength = row.getLastCellNum();
//得到指定的单元格
Cell cell = row.getCell(0);
for (int i = 1; i < rowLength; i++) {
row = sheet.getRow(i);
for (int j = 0; j < colLength; j++) {
cell = row.getCell(j);
if (cell != null) {
cell.setCellType(Cell.CELL_TYPE_STRING);
String data = cell.getStringCellValue();
data = data.trim();
if (StringUtils.isNumeric(data))
list.add(Integer.parseInt(data));
}
}
}
} catch (Exception e) {
LOGGER.error("parse excel file error :", e);
}
return shopIds;
}
}
关于前端输入汉字,传到后端的controller层乱码问题,确定前端页面设置的是UTF-8
原因:Spring MVC 是基于Servlet,在Http请求到达Servlet解析之前,GET过来的URL已经被Tomcat先做了一次URLDecode。
Tomcat对GET方式默认的URL解码结果是iso-8859-1而不是UTF-8!
解决办法1:
decodeFName = new String(fName.getBytes("iso-8859-1"),"utf-8");
解决方法2:
进入Tomcat的安装目录下,conf目录下找到server.xml文件,配置如下,主要添加 URIEncoding="UTF-8"就好了
建议第二种,一劳永逸
参考链接:https://segmentfault.com/a/1190000013796215#articleHeader5
主要遇到的问题:
1.前端组件使用问题
2.前端请求的相对路径,被upload组件自动补全了前缀,导致请求到不了后端
3.post请求的汉字到了后端的controller层乱码。
至此,前后端联调完毕,done。后端的去写前端真的心累,此文记录下这两天的摸索吧。