最近负责后台,要实现一个导入excel表格的功能,费了一些时间才实现功能,现在记录下来,分享一下:
1).controller中实现的方法:
@RequestMapping("uploadExcel.htm")
public void fileUpload(@RequestParam("excelFile") MultipartFile file,Boolean rename,String callback,HttpServletResponse response){
String message = "";
String json = "";
int result1=2;
StringBuffer buf = null ;
System.out.println(file.getOriginalFilename());
if (file != null && !file.isEmpty()) {
try {
int countError =0; //错误数目
String filename = file.getOriginalFilename();
buf = new StringBuffer();
if(! (filename.endsWith("xls") || filename.endsWith("xlsx")) ){
System.out.println("请上传扩展名为xls的文件");
}
String extName = filename.substring(filename.lastIndexOf(".") + 1);//扩展名
if (file != null && !file.isEmpty()){
String[][] result = ReadExcelUtils.getData(extName,file.getInputStream(), 1);
int rowLength = result.length;
List<Video> list = new ArrayList<Video>(); // 前500条数据存在list中
List<List<Video>> outList = new ArrayList<List<Video>>(); //存满500条数据,将list集合放入outList中
Long parentId = null;//
for (int i = 1; i <= rowLength; i++) {
System.out.println("正在处理第" + i + "条数据");
String[] column = result[i-1];
Video video = new Video();
String var = column[0].trim();
if (var.length() > 0){
Partners partners = partnersService.searchByName(var);//(这块是根据名称需要在其他表中查询信息,如果没有需要可以参考下面名称格式,直接设置值即可)
if (partners!=null) {
video.setPartnerId(partners.getId());
video.setPartnerName(var);
}else {
buf.append("第"+ i +"行合作不存在,");
countError++;
continue;
}
}else{
buf.append("第"+ i +"行合作为空,");
countError++;
continue;
}
var = column[1].trim();
if (var.length() > 0){
video.setName(var);
}else{
buf.append("第"+ i +"行名称为空,");
}
//判断错误是否大于20
if (countError > 20){
break;
}
list.add(video);
//存满500条数据,将list集合放入outList中
if (list.size()>=500){
outList.add(list);
list = new ArrayList<Video>();
}
}
if(list.size() > 0) outList.add(list);
if (buf.toString().length() > 0){
result1 = 2;
message = "错误信息:"+ buf.toString() ;
json = "{\"result\":"+result1+",\"message\":\""+message+"\"}";
printObject(response,"<script>parent."+callback+"('"+json+"');</script>");
return ;
}
for(List<Video> videoList : outList){
// 取出outList中的数据,并将数据存入数据库中
videoService.saveExcelToSQL(videoList);
}
System.out.println("导入成功");
}
} catch(Exception e){
e.printStackTrace();
}
result1 = 1;
message = buf.toString() ;
json = "{\"result\":"+result1+",\"message\":\""+message+"\"}";
printObject(response,"<script>parent."+callback+"('"+json+"');</script>");
}else {
result1 = 2;
message = "请选择文件";
json = "{\"result\":"+result1+",\"message\":\""+message+"\"}";
printObject(response,"<script>parent."+callback+"('"+json+"');</script>");
}
}
2).list.html中提交文件
<div style="width: auto;height: auto;vertical-align: middle;" align="center">
<form id="uploadImg" method="POST" enctype="multipart/form-data" action="video/uploadExcel.htm" target="uploadImgFrame">
<input type="hidden" name="callback" id="img_callback" value="img_callback"/>
<iframe id="uploadImgFrame" name="uploadImgFrame" style="display: none;"></iframe>
<table class="editTable">
<tr>
<td class="title" style="width:40%">选择文件:</td>
<td class="content">
<input id="fileid" name="excelFile" type="file" />
</td>
<td style="padding-left: 20px; "><input type="button" onclick="submit_img();" value="导入excel表"/></td>
</tr>
</table>
</form>
</div>
3). 通过service层save方法,将数据保存到数据库中
@Override
public ResultBase saveExcelToSQL(List<Video> videoList) {
for (Video video : videoList) {
try {
video.setOrderNum(num);
video.setOnline(1);
video.setCreateTime(DateUtils.getToday( "yyyy-MM-dd HH:mm:ss"));
videoDao.insert(video);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
4). js回调获取结果
function img_callback(result){
$.messager.progress('close');
var data = JSON.parse(result);
if (data.result==1) {
alert("导入成功 :"+data.message);
$('#video_grid').datagrid('reload');
} else {
alert("导入失败 :"+data.message);
}
if(imgCallback) imgCallback(data);
}
关键代码就是这些,需要注意的就是导入时对文档字段的需求,哪些字段不能为空,哪些可以为空;
printObject()方法可以将结果返回到html界面,如果你的界面使用jsp实现,并且对返回的界面没有硬性要求的话,可以自己写界面,将controller的返回值更改为String类型,用controller和jsp界面交互方法,直接返回到自定义界面同样可以。
至于原理,传excel文档和传图片本质上是一个道理,将上传的文件转化为流,将流传到服务器,由服务器进行接收保存。当然这些,都已经封装成工具类了,程序猿们在使用的时候,只需要将工具类导入就可以。我整理之后,会将代码贴出来。
补充:今天(16.06.16)同事测试的时候发现:如果在excel中直接设置名称为数字
,那么导入名称的时候,后台接收到的值为**.00,也就是默认带两位小数的,(这个debug可以看到,)这样,再用这个值去后台查询就查询不到数据了,所以如果出现数据中带数字的,导入的时候一定要注意,需要再验证之前,先用replace方法,将数字后面的”.00”去掉。