springboot 批量下载附件接口,打包成zip

前言

springboot是很流行的框架,文件下载接口也是开发中很简单常见的接口,但是批量附件下载呢?将多个附件打包成zip呢?虽然确实是很简单的一个事情,但是写还是要花点时间来捋一下,前几天刚做过这个需求,就当作笔记记录下来吧

思路

思路其实很简单,我的思路是:

  1. 随意找一个在当前物理机器上存在的目录,鉴于程序最终运行的坏境可能会有很大不同,如:linux服务器、容器等等,所以动态获取classpath
  2. 在步骤1中找到的存在的目录下,新建一个临时目录
  3. 将所要下载的文件复制到此临时目录下
  4. 使用工具将临时目录打包成一个zip文件
  5. 使用流将zip文件写回到响应中
  6. 删除临时目录和zip文件

代码

坏境是springboot项目,另外使用了hutool的一些工具类,springboot依赖项目不能随意变动,此处只贴hutool依赖:

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
            <scope>compile</scope>
        </dependency>

Controller

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;

/**
 * @Author: liang.qin
 * @Date: 2023/2/24 22:13
 * @Email: <a href="mailto:liang.qin.work@foxmail.com">liang.qin</a>
 * @Description:
 **/

@RestController
@RequestMapping("/file/")
public class FileController {

    @Autowired
    private FileServiceImpl fileService;

    /**
     * 批量下载附件,打包成zip
     * @param response 响应,将流写回
     */
    @GetMapping("/down/zip/")
    public void downToZip(HttpServletResponse response) throws FileNotFoundException {
        fileService.downToZpi(response);
    }
}

实现类

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ZipUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * @Author: liang.qin
 * @Date: 2023/2/24 22:17
 * @Email: <a href="mailto:liang.qin.work@foxmail.com">liang.qin</a>
 * @Description:
 **/

@Service
public class FileServiceImpl {

    // 批量下载附件,将其打包为zip
    public void downToZpi(HttpServletResponse response) throws FileNotFoundException {
        // 获取类路径
        String classPath = ResourceUtils.getURL("classpath:").getPath();
        // 临时目录 以uuid+时间戳 为目录名称
        String temp = classPath + IdUtil.simpleUUID() + System.currentTimeMillis();
        // 临时目录如果存在则删除
        File tempDir = new File(temp);
        if (tempDir.exists()) FileUtil.del(tempDir);
        // 创建临时目录
        boolean mkdir = tempDir.mkdir();
        File zipFile = null;
        if (mkdir) {
            try {
                // 此处应根据传递进来的业务参数确定需要下载的物理文件资源,模拟文件资源如下:
                List<String> targets = Arrays.asList("D:\\temp\\img1.jpg","D:\\temp\\img2.jpg","D:\\temp\\img3.jpg");
                if (CollUtil.isNotEmpty(targets)) {
                    // 将需要下载的文件复制到临时目录中 TODO 如果此处文件比较多,可采取并行复制
                    targets.forEach(x->FileUtil.copyFile(new File(x),
                            // 拼接文件名称
                            new File(temp+File.separator+x.substring(x.lastIndexOf("\\")+1))));
                    // 将临时目录压缩成zip
                    zipFile = ZipUtil.zip(temp);

                    try (
                            InputStream in = new FileInputStream(zipFile);
                            ServletOutputStream os = response.getOutputStream()
                    ) {
                        int len;
                        byte[] buffer = new byte[1024];
                        while ((len = in.read(buffer)) > 0) {
                            os.write(buffer, 0, len);
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }

                    // 设置响应的一些格式
                    String encodedFileName = URLEncoder.encode("所有附件.zip", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
                    response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
                    response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", encodedFileName));
                    response.setHeader("Pragma", "no-cache");
                    response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
                    response.setHeader("Expires", "0");
                }
            } catch (RuntimeException e) {
                // 此处应该记录日志
                e.printStackTrace();
            } finally {
                // 删除临时目录和压缩后的文件
                FileUtil.del(tempDir);
                FileUtil.del(zipFile);
            }
        }
    }
}

效果图

调用下载接口
调用下载接口

下载zip解压后目录
在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值