多个文件打成压缩包(zip)并下载

1.controller层

package com.xxx.qrcode.commons.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.xxx.qrcode.applyrecord.model.QualificationUpload;
import com.xxx.qrcode.commons.constant.Constants;
import com.xxx.qrcode.commons.utils.web.JSONUtils;
import com.xxx.qrcode.facility.model.Resources;
import com.xxx.qrcode.facility.service.ResourcesService;

/**
 * 下载文件支持批量下载
 * 基于ant.jar包中的org.apache.tools.zip.*完成压缩
 */
@Controller
@RequestMapping("/fileDownLoadZipController/*")
public class FileDownLoadZipController {
    private Logger logger = Logger.getLogger(FileDownLoadZipController.class);
    /**
     * 文件服务器地址
     */
    public final String resourcePath = Constants.FILE_PATH;

    @Resource
    private ResourcesService resourcesSercice;
    /**
     * 文件访问映射
     */
//    @Value("#{properties['resourceIP']}")
//    private String resourceIP;

    /**
     * 文件下载<span>批量下载已压缩包的方式实现,单文件已流的方式实现</span>
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "downLoadZipFile", method = RequestMethod.POST)
    public Map<String, Object> download(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        // 文件流输出
        FileOutputStream outStream = null;
        // 压缩流
        ZipOutputStream zipOutputStream = null;
        try {
            String params = request.getParameter("params");
            QualificationUpload qualificationUpload = JSONUtils.jsonToBean(params, QualificationUpload.class);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id", qualificationUpload.getId());
            map.put("type", qualificationUpload.getType());
            List<Resources> resourcesList = resourcesSercice.queryResourcesList(map);
            /**
             * 下载集合
             */
            List<String> result = new ArrayList<String>();
            for (int i = 0; i < resourcesList.size(); i++) {
                Resources resources = resourcesList.get(i);
                if (null != resources && null != resources.getUrl() && resources.getUrl() != "") {
                    result.add(resources.getUrl());
                }
            }
            /**
             * 数据集不为空时,组装下载数据.数据集大于1时,采用打包方式实现批量下载;数据集为1时,单个下载文件
             */
            if (null != result && !result.isEmpty() && result.size() > 0) {
                if (result.size() > 1) {
                    // 临时压缩文件
                    String downloadFileName = new Date().getTime() + ".zip";
                    // 服务器临时下载路径
                    String downloadFileUrl = resourcePath + downloadFileName;
                    File zipFile = new File(downloadFileUrl);
                    // 文件流输出
                    outStream = new FileOutputStream(zipFile);
                    // 压缩流
                    zipOutputStream = new ZipOutputStream(outStream);
                    zipOutputStream.setEncoding("GBK");// 解决中文乱码
                    for (int i = 0; i < result.size(); i++) {
                        String url = (String) result.get(i);
                        //http://192.168.1.253:8089  截取
                        url = resourcePath + url.substring(25);
                        File file = new File(url);// 目标文件
                        // 读写入权限
                        file.setWritable(true, false);
                        file.setReadable(true, false);
                        if (file.exists()) {
                            zipFile(file, zipOutputStream);
                        }
                    }
                    zipOutputStream.close();
                    outStream.close();
                    downloadZip(zipFile, response, request);
                } else {
                    String url = (String) result.get(0);
                    url = resourcePath + url;
                    File file = new File(url);
                    // 读写入权限
                    file.setWritable(true, false);
                    file.setReadable(true, false);
                    if (file.exists()) {
                        downloadZip(file, response, request);
                    }
                }
            } else {
                logger.error("FileDownLoadBatchController.download:Collection Is Empty!");
            }
        } catch (Exception e) {
            logger.error("FileDownLoadBatchController.download:", e);
        }
        return resultMap;
    }

    /**
     * 将文件写入zip包中
     * @param inputFile
     *                      文件
     * @param outputstream
     *                      zip输出流
     */
    private void zipFile(File inputFile, ZipOutputStream outputstream) {
        try {
            if (inputFile.exists()) {
                if (inputFile.isFile()) {
                    FileInputStream inStream = new FileInputStream(inputFile);
                    BufferedInputStream bInStream = new BufferedInputStream(inStream);
                    ZipEntry entry = new ZipEntry(inputFile.getName());
                    outputstream.putNextEntry(entry);
                    final int MAX_BYTE = 10 * 1024 * 1024; // 最大的流为10M
                    long streamTotal = 0; // 接受流的容量
                    int streamNum = 0; // 流需要分开的数量
                    int leaveByte = 0; // 文件剩下的字符数
                    byte[] inOutbyte; // byte数组接受文件的数据
                    streamTotal = bInStream.available(); // 通过available方法取得流的最大字符数
                    streamNum = (int) Math.floor(streamTotal / MAX_BYTE); // 取得流文件需要分开的数量
                    leaveByte = (int) streamTotal % MAX_BYTE; // 分开文件之后,剩余的数量
                    if (streamNum > 0) {
                        for (int j = 0; j < streamNum; ++j) {
                            inOutbyte = new byte[MAX_BYTE];
                            // 读入流,保存在byte数组
                            bInStream.read(inOutbyte, 0, MAX_BYTE);
                            // 写出流
                            outputstream.write(inOutbyte, 0, MAX_BYTE);
                        }
                    }
                    // 写出剩下的流数据
                    inOutbyte = new byte[leaveByte];
                    bInStream.read(inOutbyte, 0, leaveByte);
                    outputstream.write(inOutbyte);
                    // Closes the current ZIP entry and positions the stream for
                    // writing the next entry
                    outputstream.closeEntry();
                    // 关闭
                    bInStream.close();
                    inStream.close();
                }
            } else {
                logger.error("FileDownLoadBatchController.zipFile:Not Found File!");
            }
        } catch (IOException e) {
            logger.error("FileDownLoadBatchController.zipFile:", e);
        }
    }

    /**
     * 下载zip文件
     * @param file
     *                  zip文件
     * @param response
     *                  HttpServletResponse
     * @param request
     *                  HttpServletRequest
     */
    public void downloadZip(File file, HttpServletResponse response, HttpServletRequest request) {
        try {
            // 以流的形式下载文件。
            BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            /*
             * 解决各浏览器的中文乱码问题
             */
            String fileName = file.getName();
            String userAgent = request.getHeader("User-Agent");
            byte[] bytes = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes("UTF-8"); // fileName.getBytes("UTF-8")处理safari的乱码问题
            fileName = new String(bytes, "ISO-8859-1"); // 各浏览器基本都支持ISO编码
            response.setHeader("Content-Length", String.valueOf(buffer.length));
            // response.setHeader("Content-Disposition", "attachment;filename="
            // + file.getName());
            response.setHeader("Content-Disposition", String.format("attachment; filename="%s"", fileName));
            outputStream.write(buffer);
            outputStream.flush();
            outputStream.close();

            if (null != fileName && fileName != "" && fileName.contains(".zip")) {
                // 将生成的服务器端文件删除
                file.delete();
            }
        } catch (IOException e) {
            logger.error("FileDownLoadBatchController.downloadZip:", e);
        }
    }
}

2.js部分   前台框架是AngularJS

 /**
         * 文件下载
         * @param url
         *                 下载地址
         */
        download : function(qualificationUpload){
            if(null != qualificationUpload && qualificationUpload != '' && qualificationUpload != undefined){
                var qualificationUploadStr = JSON.stringify(qualificationUpload)
                jQuery('#params').val(qualificationUploadStr);
                jQuery('#fileDownload').submit();
            } else {
                zsAlert($ZSPLAT,$scope,'文件不存在!');
            }
        },

3.html页面

<a href="javascript:void(0)" ng-click="qualificationUploadController.download(qualificationUpload)">下载</a>
<form action="fileDownLoadZipController/downLoadZipFile" method="post" id="fileDownload">
<input type="hidden" id="params" name="params" value="" />
</form>
原文地址:https://www.cnblogs.com/zhou-pan/p/9922203.html