1、前言
上传图片一般采用异步上传的方式,但是异步上传带来不好的地方,就如果图片有改变或者删除,图片服务器端就会造成浪费。所以有时候就会和参数同步提交。笔者喜欢base64图片一起上传,但是图片过多时就会出现数据丢失等异常。因为tomcat的post请求默认是2M的长度限制。
2、解决办法
有两种:
① 修改tomcat的servel.xml的配置文件,设置 maxPostSize=“-1”,来取消post请求参数的限制
② 图片压缩层Zip文件,作为一个文件上传。(今天记录一下后者的简单编写)
3、依赖坐标
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.9.4</version>
</dependency>
这个依赖有点“重”,也可以选择其他第三方插件
4、上代码
@RequestMapping("/upload")
@ResponseBody
public JsonResult upload(@RequestParam("zipFile")MultipartFile zipFile) throws IOException{
// 获取上传的文件
CommonsMultipartFile commonsMultipartFile = (CommonsMultipartFile)zipFile;
// 将CommonsMultipartFile转化成java.io.File。 这里转化还可以使用tranferTo方法
DiskFileItem fileItem = (DiskFileItem)commonsMultipartFile.getFileItem();
File file = fileItem.getStoreLocation();
// 这里的ZipFile为: org.apache.tools.zip.ZipFile jdk自带的ZipFile没有getEntries方法
ZipFile zipFile = new ZipFile(file);
Enumeration<ZipEntry> entries = zipFile.getEntries();
while(entries.hasMoreElements()){
ZipEntry zipEntry = entries.nextElement();
InputStream is = zipFile.getInputStream(zipEntry);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 使用IOUtils工具类
org.apache.commons.io.IOUtils.copy(is, bos);
is.close();
bos.close();
// 文件上传
String uploadFile = dfsService.uploadFile(bos.toByteArray(), zipEntry.getName());
System.out.println(uploadFile);
}
return new JsonResult(true);
}
本文值只做了简单的实现,实际应用需要多种校验。
5、前端页面压缩的代码
使用zip包上传是为了减少传输的数量,这里使用jsZip这个前端工具实现打包,最终以二进制流的方式上传。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>测试JSZIP</title>
</head>
<body>
<input type="file" id="file" />
<img src="" id="image">
</body>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/jszip.js"></script>
<script type="text/javascript">
$(function(){
$("#file").change(function(){
var file = this.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(){
// 获取base64图片
var imgData = this.result;
// 取消base64图片的标识
var base64 = imgData.substring(imgData.indexOf(",")+1);
// 使用JSZip打包
var zip = new JSZip();
zip.file("car.jpg", base64, {base64: true});
zip.file("car2.jpg", base64, {base64: true});
zip.file("car3.jpg", base64, {base64: true});
zip.generateAsync({type:"blob"}).then(function(content) {
var formData = new FormData();
// content 为二进制流的形式,后台接收的类型为:application/zip
formData.append("zipFile", content);
$.ajax({
url:"http://127.0.0.1/upload",
type:"POST",
data:formData,
processData: false, //processData 默认为false,当设置为true的时候,jquery ajax 提交的时候不会序列化 data,而是直接使用data
contentType: false,
success:function(){
alert("上传成功!")
}
});
});
}
});
});
6、注意事项
- 单张图片上传,ajax使用FormData以Blob或者File(Blob的更具体的实现)的形式,上传的时候会以binary(二进制字节流)的形式上传,使用MultipartFile对象接收,没有问题。
- 如果多张图片使用Blob[]上传,传递的参数会你变成[Object blob],后台无法使用MultipartFile接收参数,使用时注意!
7、参考文档
jsZip官方文档:https://stuk.github.io/jszip/
-- END