base64图片打成Zip包上传,以及服务端解压的简单实现

469 阅读2分钟

base64图片打成Zip包上传,以及服务端解压的简单实现

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();    // 生成的文件一般会存在内存中,超过阈值,会生成临时文件,文件不用时会自动删除,详见FileItemFfactory    File file = fileItem.getStoreLocation();    */    
    // 上面的方法应用中可能会稍有问题,文件可能过早删除,导致找不到临时文件,故需要手动创建临时文件    
    // 创建临时文件夹
    String rootPath = session.getServletContext().getRealPath("/");
    File temDir = new File(rootPath + File.separator + UUID.randomUUID().toString().replaceAll("-", ""));
    if(!temDir.exists()){
    temDir.mkdirs();
    }
    File tempZip = new File(temDir, System.currentTimeMillis()+".tmp");
    commonsMultipartFile .transferTo(tempZip);    
    // 这里的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);
    }
    // 删除临时文件和文件夹
    zipFile.close(); //zipFile是流文件,必须关闭才能删除文件和文件夹
    if (tempZip != null) {
    tempZip.delete();
    }
    temDir.delete();
    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" src="js/cropper.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.js"></script>
<script type="text/javascript">
    $(function() {
        $("#file").change(function () {
            var file = this.files[0];
            var reader = new FileReader();
            reader.readAsDataURL(file);
            var base64 = "";
            reader.onload = function () {
                var imgData = this.result;
                $("#image").attr("src", imgData);
 
                var zip = new JSZip();
                // 向zip文件中添加图片,可以添加多个文件或者图片,此处以图片为例
                // base64图片需要去掉base64图片标识
                zip.file("car.jpg", imgData.substring(imgData.indexOf(",") + 1), {base64: true});
                zip.generateAsync({
                        type: "blob",  // 压缩类型
                        compression: "DEFLATE",      // STORE:默认不压缩 DEFLATE:需要压缩
                        compressionOptions: {
                            level: 9  // 压缩等级1~9    1压缩速度最快,9最优压缩方式
                            // [使用一张图片测试之后1和9压缩的力度不大,相差100字节左右]
                        }
                    })
                   .then(function (content) {
                    // 压缩的结果为blob类型(二进制流),可用作文件上传
                    console.info(content);
                    // 直接在浏览器打成car.zip包并下载,saveAs依赖的js是FileSaver.js
                    saveAs(content, "car.zip");
                });
            }
        });
    });
</script>
</html>

6、注意事项

  • 单张图片上传,ajax使用FormData以Blob或者File(Blob的更具体的实现)的形式,上传的时候会以binary(二进制字节流)的形式上传,使用MultipartFile对象接收,没有问题。
  • 如果多张图片使用Blob[]上传,传递的参数会你变成[Object blob],后台无法使用MultipartFile接收参数,使用时注意!

7、参考文档

jsZip官方文档:JSZip

-- END