Java中多目录文件压缩成zip(原生)<二>

Java文件压缩成zip,处理base64和url(原生)<一>
将多个文件打包到zip提供给用户下载,抽离出来了一个工具类,支持单文件、多文件、按类型的多文件的压缩和下载。

1.实体类

import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * @date 2022/5/25 15:11
 * @description:
 */
@Data
public class ZipDto implements Serializable {

    /**类型名称/子目录名称*/
    private String typeName;

    /**文件路径*/
    private String fileUrl;

    /**
     * 分类型时,集合有值
     * 文件路径集合
     */
    private List<String> urlList;
}

2.工具类

主要方法:

  1. downZipListType: 允许用户按类型将文件列表打包成zip文件进行下载。
  2. downZipList: 提供批量下载功能,可以将多个文件一起打包成zip文件。
  3. downZipOne: 为单个文件提供下载功能,虽然是单个文件,但为了保持统一性,仍然会将其打包成zip格式。

删除了项目敏感import,自行导入实体即可。

import cn.hutool.core.util.StrUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @date 2023/10/18 17:32
 * @description:
 */
@Slf4j
@UtilityClass
public class CustomOriZipUtils {

    private static final String SUFFIX_ZIP = ".zip";
    private static final String UNNAMED = "未命名";

    /**
     * 按类型批量下载。
     */
    public static void downZipListType(List<ZipDto> list, String fileName, HttpServletRequest request, HttpServletResponse response) {
        try (ZipOutputStream zos = createZipOutputStream(response, request, fileName)) {
            for (ZipDto dto : list) {
                writeToZipStream(dto.getUrlList(), zos, dto.getTypeName());
            }
        } catch (Exception e) {
            log.error("创建zip文件出错", e);
        }
    }

    /**
     * 批量下载。
     */
    public static void downZipList(List<ZipDto> list, String fileName, HttpServletRequest request, HttpServletResponse response) {
        try (ZipOutputStream zos = createZipOutputStream(response, request,fileName)) {
            for (ZipDto dto : list) {
                writeToZipStream(Collections.singletonList(dto.getFileUrl()), zos, dto.getTypeName());
            }
        } catch (Exception e) {
            log.error("创建zip文件出错", e);
        }
    }

    /**
     * 下载单个记录。
     */
    public void downZipOne(ZipDto dto, String fileName, HttpServletRequest request, HttpServletResponse response) {
        try (ZipOutputStream zos = createZipOutputStream(response, request,fileName)) {
            writeToZipStream(Collections.singletonList(dto.getFileUrl()), zos, dto.getTypeName());
        } catch (Exception e) {
            log.error("创建zip文件出错", e);
        }
    }

    /**
     * 为下载设置响应。
     */
    private void setResponse(HttpServletResponse response, HttpServletRequest request,String fileName) throws UnsupportedEncodingException {
        if (StrUtil.isAllBlank(fileName)) {
            fileName = LocalDate.now() + UNNAMED;
        }
        if (!fileName.endsWith(SUFFIX_ZIP)) {
            fileName += SUFFIX_ZIP;
        }
        fileName = encodeFileName(request, fileName);
        response.setHeader("Connection", "close");
        response.setHeader("Content-Type", "application/octet-stream;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    }

    /**
     * 将URL写入zip流中。
     */
    private static void writeToZipStream(List<String> urls, ZipOutputStream zos, String subDir)  {
        byte[] buffer = new byte[1024];
        for (String url : urls) {
            if (StrUtil.isNotBlank(url)) {
                try (InputStream is = new URL(url).openStream()) {
                    String fileName = StrUtil.isAllBlank(subDir) ? getFileName(url) : subDir + "/" + getFileName(url);
                    zos.putNextEntry(new ZipEntry(fileName));
                    int length;
                    while ((length = is.read(buffer)) > 0) {
                        zos.write(buffer, 0, length);
                    }
                    zos.closeEntry();
                } catch (Exception e) {
                    log.error("将文件 [{}] 写入zip时出错", url, e);
                }
            }
        }
    }

    /**
     * 根据浏览器类型编码文件名。
     */
    private static String encodeFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
        String userAgent = request.getHeader("USER-AGENT");
        if (userAgent.contains("Firefox")) {
            return new String(fileName.getBytes(), "ISO8859-1");
        }
        return URLEncoder.encode(fileName, "UTF-8");
    }

    /**
     * 创建ZipOutputStream并设置响应头。
     */
    private static ZipOutputStream createZipOutputStream(HttpServletResponse response,HttpServletRequest request, String fileName) throws IOException {
        setResponse(response, request,fileName);
        return new ZipOutputStream(response.getOutputStream());
    }

    /**
     * 从url获取文件名
     * @param url
     * @return
     */
    public String getFileName(String url) {
        return url.substring(url.lastIndexOf('/') + 1);
    }

3.效果

多目录文件压缩下载:
图片.png
单文件打包下载:
图片.png


万物皆有裂缝,那是光照进来的地方 – 莱昂纳德·科恩

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值