做项目的时候碰到了文件上传,这是很常见的需求,但是往往以小见大,文件大小,类型或者是其他的各种校验往往很头疼,所以自己来简单做了一个Demo供大家参考
GitHub - MovingBricksG/fileupload: 兼容IE8的文件上传Demo
Demo架构
此次为了方便快速的搭建,使用了SpringBoot结合thymeleaf来作展示
需要注意的事情!!!!
①IE浏览器各个版本不同,对于input的file域操作也不同,像IE8根本无法操作file域的内容,着实令人头疼
②后台接口的类型要设置为String,并且在@RequestMapping 中要配置参数produces = "text/plain;charset=UTF-8",要不在IE8上会出现——上传文件时出现奇奇怪怪的弹框,让你下载或是什么(具体忘记了)
主要代码
- 后台代码
package com.gch.fileupload.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gch.fileupload.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.IOException;
import java.util.*;
@RestController
public class FileUploadController {
private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class);
/**
* 文件上传接口,请切记不要忘了加 produces = "text/plain;charset=UTF-8"
* 否则在IE上点击上传时候会出现下载的小窗口
* @param multRequest
* @return
* @throws IOException
*/
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "text/plain;charset=UTF-8")
public String insertAttachment(MultipartHttpServletRequest multRequest) throws IOException {
// 文件上传的特殊性,需要返回String类型
Map<String, Object> resultMap = new HashMap<>();
// 成功和失败列表,根据自己的逻辑放入
List<String> successList = new ArrayList<>();
List<String> failList = new ArrayList<>();
//上传多个文件到文件表
Iterator<String> fileNames =multRequest.getFileNames();
Map<String, MultipartFile> fileMap = multRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
MultipartFile mf = entry.getValue(); // 获得原始文件名
String fileName = mf.getOriginalFilename(); // 截取文件类型; 这里可以根据文件类型进行判断
LOGGER.info(fileName);
successList.add(fileName);
// TODO 文件上传到文件服务器
// 可以利用 FileCopyUtils.copy(mf.getBytes(), new File(filePath));
}
// 封装返回结果(返回结果根据具体需求)
ObjectMapper mapper = new ObjectMapper();
resultMap.put("dataSuccess", successList);
resultMap.put("dataFail", failList);
LOGGER.info(mapper.writeValueAsString(resultMap));
return mapper.writeValueAsString(resultMap);
}
}
package com.gch.fileupload.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 对静态html的映射
*/
@Controller
public class WebController {
@RequestMapping(value="/{name}")
public String commonController(@PathVariable String name) {
return name;
}
}
- 前台代码
/**
* 上传文件modal框绑定事件(一般浏览器)
* @param el 选择完成后要回显的面板
*/
function fileUploadNormal (el) {
var $normalModalUpload = $('#normalModalUpload');
$normalModalUpload.on({
'shown.bs.modal': function () {
$('#addFile').on('click', function () {
var lis = $('.inputUL').find('li');
if (lis.length >= 5) {
toaster('文件上传最多支持5个文件', '', 'info');
return false;
}
$('#normalFiles').trigger('click');
});
uploadChange(el);
$('#confirmUpload').on('click', function () {
loadingModal();
// 去除保存成功modal框
loadingModalEvent(function () {
$('#fileForm').ajaxSubmit({
url : '/upload',
type : 'post',
ContentType : 'multipart/form-data',
// ContentType必须
success : function(res) {
var data = JSON.parse(res);
var dataSuccess = data.dataSuccess;
if (isNotEmpty(dataSuccess)) {
$('#saveMessage').empty().append('文件上传成功');
setTimeout(function () {
$('#loadingModal').modal('hide');
}, 500);
// 进行回显
var content = [];
dataSuccess.forEach(function (item) {
content.push('<span class="file-option ">'+item+'</span>');
});
el.append(content.join(''));
}else{
$('#saveMessage').empty().append('文件上传失败');
$('#loadingModal').modal('hide');
toaster('上传失败', '', 'error');
}
$normalModalUpload.modal('hide');
},
error : function() {
$('#saveMessage').empty().append('文件上传失败');
$('#loadingModal').modal('hide');
toaster('上传失败', '', 'error');
}
});
});
});
},
'hidden.bs.modal': function () {
$(this).remove();
}
}).modal('show');
}
总结
文件上传难点在于对文件的校验和对浏览器兼容的问题,所有前端js先对浏览器进行了判断,若是IE系列,会走另外一个方法;
详情代码请自行下载阅读