Java Web 单文件下载与多文件压缩下载

279 阅读2分钟

单文件导出

/**
 * 导出文件
 *
 * @param filePath 文件路径
 * @param response response
 */
public void dowanload(String filePath, HttpServletResponse response) {
    // 将地址转换为文件对象
    File file = new File(filePath);
    
    // 文件对象转byte数组
    byte[] fileBytes;
    try (FileInputStream fis = new FileInputStream(file)) {
        fileBytes = new byte[(int) file.length()];
        fis.read(fileBytes);
    } catch (Exception e) {
        // 自定义处理
    }
    
    // 设置response参数
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/octet-stream;charset=utf-8");
    response.setContentType("multipart/form-data");
    try {
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes("gbk"), "iso8859-1"));
    } catch (UnsupportedEncodingException e) {
        // 自定义处理
    }
    
    try (ServletOutputStream stream = response.getOutputStream()) {
        stream.write(fileBytes);
        stream.flush();
    } catch (IOException e) {
        // 自定义处理
    }
}

多文件压缩导出

/**
 * 导出压缩文件
 *
 * @param filePathList 文件路径
 * @param response     response
 */
public void downloadZip(List<String> filePathList, HttpServletResponse response) {
    // 设置response参数
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/octet-stream;charset=utf-8");
    response.setContentType("multipart/form-data");
    try {
        response.setHeader("Content-Disposition", "attachment;filename=" + new String("压缩文件".getBytes("gbk"), "iso8859-1"));
    } catch (UnsupportedEncodingException e) {
        // 自定义处理
    }

    try {
        ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
        File file;
        ZipEntry zipEntry;
        for (String item : filePathList) {
            file = new File(item);

            //创新新的ZipEntry
            zipEntry = new ZipEntry(file.getName());
            zipOut.putNextEntry(zipEntry);

            // 文件对象转byte数组
            byte[] fileBytes;
            try (FileInputStream fis = new FileInputStream(file)) {
                fileBytes = new byte[(int) file.length()];
                fis.read(fileBytes);
            } catch (Exception e) {
                // 自定义处理
            }
            zipOut.write(fileBytes);
        }
        zipOut.close();
    } catch (IOException e) {
        // 自定义处理
    }
}

多文件分组压缩下载

文件格式像下面格式,需要将图片分组写入不同的文件夹再一起压缩导出。

graph TD
压缩文件 --> 文件夹A
压缩文件 --> 文件夹B
压缩文件 --> 文件夹C
文件夹A --> 文件a
文件夹B --> 文件b
文件夹B --> 文件c
文件夹B --> 文件d
文件夹C --> 文件e
文件夹C --> 文件f
public class FileDownloadEntity {
   
    /**
     * 文件夹名称
     */
    private String folderName;

    /**
     * 文件路径
     */
    private List<String> filePathList;

    public String getFolderName() {
        return folderName;
    }

    public void setFolderName(String folderName) {
        this.folderName = folderName;
    }

    public List<String> getFilePathList() {
        return filePathList;
    }

    public void setFilePathList(List<String> filePathList) {
        this.filePathList = filePathList;
    }
}

/**
 * 导出压缩文件
 *
 * @param list         导出参数
 * @param response     response
 */
public void downloadZip(List<FileDownloadEntity> list, HttpServletResponse response) {
    File rootFile = new File(System.getProperty("java.io.temDir") + System.currentTimeMillis());
    if (!rootFile.exists()) {
        // 使用hutool.core工具包
        FileUtil.mkdir(rootFile);
    }
    
    for (FileDownloadEntity entity : list) {
        File secondFile = new File(rootFile, entity.getFolderName());
        if (!secondFile.exists()) {
            FileUtil.mkdir(secondFile);
        }
        for (String filePath : entity.getFilePathList()) {
            File imgFile = new File(filePath);
            //获得文件内容
            byte[] bytes = convertFileToByte(imgFile);
            File file = new File(secondFile, imgFile.getName());
            try (FileOutputStream outputStream = new FileOutputStream(file)) {
                outputStream.write(bytes);
            } catch (Exception e) {
                throw new BusinessException(ResultCodeEnum.FILE_DOWNLOAD_FAILED, e);
            }
        }
    }
    File zipFile = ZipUtil.zip(rootFile);
    byte[] fileBytes = convertFileToByte(zipFile);
    // 设置response参数 
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/octet-stream;charset=utf-8");
    response.setContentType("multipart/form-data"); 
    try { 
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes("gbk"), "iso8859-1")); 
    } catch (UnsupportedEncodingException e) { 
            // 自定义处理 
    } 
    
    try (ServletOutputStream stream = response.getOutputStream()) {
        stream.write(fileBytes); 
        stream.flush(); 
    } catch (IOException e) { 
         // 自定义处理 
    }
    FileUtil.del(zipFile);
    FileUtil.del(rootFile);
}


/**
 * File转Byte数组
 *
 * @param file 文件对象
 * @return Byte数组
 */
private Byte[] convertFileToByte(File file) {
    // 文件对象转byte数组
    byte[] fileBytes;
    try (FileInputStream fis = new FileInputStream(file)) {
        fileBytes = new byte[(int) file.length()];
        fis.read(fileBytes);
    } catch (Exception e) {
        // 自定义处理
    }
    return fileBytes;
}

写完发布到服务器之后,前端调用之后出现了跨域的问题,就离谱,项目框架已经做过跨域处理了,而且其他方法都没出现跨域问题,单单导出的出现了,经仔细查找后发现导出在设置response参数时,第一行代码是:

response.reset();

reset方法会把之前写入的信息清除掉,之前解决跨域的处理被重置了~~~