java实现多文件地址打包zip

将多个地址文件打zip压缩包下载,地址格式可为http、windows、linux,支持zip内创建多级文件夹,同级目录下相同名称文件自动拼接数字后缀。

1、使用示例

@GetMapping("/zip")
public void zip(HttpServletResponse response) throws IOException {
    List<ZipUtils.Path> list = Arrays.asList(
            new ZipUtils.Path("https://pss.bdstatic.com/static/superman/img/topnav/newxueshuicon-a5314d5c83.png", "文件夹/图片.jpg"),
            new ZipUtils.Path("C:\\Users\\aa\\Desktop\\pic.jpg", null),
            new ZipUtils.Path("C:\\Users\\aa\\Desktop\\pic.jpg", null)
    );
    ZipUtils.zip(response, list, "文件.zip");
}

在这里插入图片描述

2、代码


import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
public class ZipUtils {

    public static void zip(HttpServletResponse response, List<Path> fileList, String filename) throws IOException {
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));

        try (ServletOutputStream os = response.getOutputStream(); ZipOutputStream zos = new ZipOutputStream(os)) {
            Set<String> existsFiles = new HashSet<>();
            for (Path data : fileList) {
                if (StrUtil.isEmpty(data.getUrl())) {
                    continue;
                }
                try {
                    String fileName = getFileName(data.getUrl(), data.getFileName(), existsFiles);

                    if (data.getUrl().startsWith("http")) {
                        zipNetwork(zos, data.getUrl(), fileName);
                    } else {
                        zipLocal(zos, data.getUrl(), fileName);
                    }
                } catch (Exception e) {
                    log.error("文件压缩错误:" + data.getUrl(), e);
                }
            }
        }
    }

    private static String getFileName(String url, String fileName, Set<String> existsFiles) {
        if (StrUtil.isEmpty(fileName)) {
            String separator = url.startsWith("http") ? "/" : File.separator;
            fileName = StrUtil.subAfter(url, separator, true);
        }
        int i = 1;
        String before = StrUtil.subBefore(fileName, ".", true);
        String after = StrUtil.subAfter(fileName, ".", true);
        while (existsFiles.contains(fileName)) {
            fileName = before + "(" + i + ")." + after;
            i++;
        }
        existsFiles.add(fileName);
        return fileName;
    }

    private static void zipNetwork(ZipOutputStream zos, String url, String fileName) throws IOException {
        try (BufferedInputStream bis = new BufferedInputStream(new URL(url).openStream())) {
            zos.putNextEntry(new ZipEntry(fileName));
            IoUtil.copy(bis, zos);
            zos.closeEntry();
        }
    }

    private static void zipLocal(ZipOutputStream zos, String url, String fileName) throws IOException {
        File file = new File(url);
        if (file.exists() && file.isFile()) {
            try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
                zos.putNextEntry(new ZipEntry(fileName));
                IoUtil.copy(bis, zos);
                zos.closeEntry();
            }
        }
    }


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Path {
        /**
         * 网络或本地文件路径
         * 例:https://pss.bdstatic.com/static/superman/img/topnav/newxueshuicon-a5314d5c83.png
         * 例:/Users/root/Documents/abc.JPG
         * 例:C:\Users\admin\Desktop\abc.xlsx
         */
        private String url;
        /**
         * 压缩包内文件名,可拼接文件夹,为空时自动截取url后缀
         * 例:文件夹/abc.JPG
         * 例:abc.JPG
         */
        private String fileName;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值