最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java將文件壓縮成zip并下載

 更新時(shí)間:2025年04月09日 09:39:33   作者:頗有幾分姿色  
這篇文章主要為大家詳細(xì)介紹了Java如何將文件壓縮成zip和下載,并處理base64和url,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下

Java文件壓縮成zip并下載

使用jdk自帶的zip包下的類來實(shí)現(xiàn)壓縮

1.實(shí)體類

實(shí)體類主要是文件名和文件路徑(base64字符串),壓縮文件路徑時(shí)可以不使用類里的文件名。

import lombok.Data;

@Data
public class FileInfoDto {
    /**文件名*/
    private String fileName;

    **文件路徑或base64字符串*/
    private String file;
}

2.工具類

創(chuàng)建和刪除文件的方式來輔助壓縮,在創(chuàng)建一個(gè)zip文件時(shí),每個(gè)zipEntry代表zip文件中的一個(gè)項(xiàng),zipEntry的名稱在zip文件內(nèi)必須是唯一的,因?yàn)閦ip文件格式使用這些條目名稱作為查找鍵,來定位和提取存儲(chǔ)在zip中的文件。所以名稱相同時(shí)會(huì)拋出異常,我這里在調(diào)用前做了處理。

我省略了項(xiàng)目路徑的import,使用時(shí)導(dǎo)入自己的路徑即可。

import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author xxx
 * @date 2023/10/18 14:43
 * @description:
 */
public class BaseZipUtils {
    /**
     * 使用給定的文件列表創(chuàng)建ZIP文件并將其發(fā)送到HTTP響應(yīng)。
     *
     * @param response HttpServletResponse
     * @param fileList 文件列表
     * @param title    ZIP文件的標(biāo)題
     * @param type  1-base64壓縮,2-url-壓縮
     */
    public static void downZipFile(HttpServletResponse response, List<FileInfoDto> fileList, String title, Integer type) {
        // 獲取模板路徑,并構(gòu)建ZIP文件的完整路徑。
        String tempDirPath = getTemplatePath();
        File zipFilePath = new File(tempDirPath, LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "_" + title);

        try {
            if (1 == type) {
                // 基于Base64編碼的文件創(chuàng)建ZIP文件。
                zipFiles(fileList, zipFilePath);
            } else {
                zipFilesFromURLs(fileList, zipFilePath);
            }

            // 如果ZIP文件存在,將其發(fā)送到HTTP響應(yīng)。
            if (zipFilePath.exists()) {
                try (InputStream is = new FileInputStream(zipFilePath);
                     OutputStream os = response.getOutputStream()) {

                    response.setContentType("application/octet-stream");
                    response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(zipFilePath.getName(), "UTF-8"));

                    // 從ZIP文件讀取內(nèi)容并寫入HTTP響應(yīng)。
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = is.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                } finally {
                    // 刪除臨時(shí)ZIP文件。
                    Files.deleteIfExists(zipFilePath.toPath());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 將Base64編碼的文件列表壓縮為一個(gè)ZIP文件。
     *
     * @param srcFiles 需要壓縮的文件列表
     * @param zipFile  生成的ZIP文件
     */
    public static void zipFiles(List<FileInfoDto> srcFiles, File zipFile) throws IOException {
        // 如果ZIP文件不存在,創(chuàng)建它。
        if (!zipFile.exists()) {
            Files.createFile(zipFile.toPath());
        }

        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            for (FileInfoDto fileInfo : srcFiles) {
                // 解碼文件名。
                String fileName = URLDecoder.decode(fileInfo.getFileName(), "UTF-8");

                // 創(chuàng)建ZIP條目并添加到ZIP輸出流中。
                ZipEntry entry = new ZipEntry(fileName);
                zos.putNextEntry(entry);

                // 將Base64編碼的文件內(nèi)容解碼為字節(jié)數(shù)組。
                byte[] fileBytes = Base64.getDecoder().decode(fileInfo.getFile());

                // 將字節(jié)數(shù)組寫入ZIP文件。
                zos.write(fileBytes);
                zos.closeEntry();
            }
        }
    }

    /**
     * 使用從URL獲取的文件列表創(chuàng)建ZIP文件。
     *
     * @param srcFilesURLs 需要壓縮的文件URL列表
     * @param zipFile      生成的ZIP文件
     */
    public static void zipFilesFromURLs(List<FileInfoDto> srcFilesURLs, File zipFile) throws IOException {
        // 如果ZIP文件不存在,創(chuàng)建它。
        if (!zipFile.exists()) {
            Files.createFile(zipFile.toPath());
        }

        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            for (FileInfoDto dto : srcFilesURLs) {
                URL url = new URL(dto.getFile());

                // 獲取文件的文件名。
                String fileName = Paths.get(url.getPath()).getFileName().toString();

                // 創(chuàng)建ZIP條目并添加到ZIP輸出流中。
                ZipEntry entry = new ZipEntry(fileName);
                zos.putNextEntry(entry);

                // 從URL讀取文件內(nèi)容。
                try (InputStream is = url.openStream()) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = is.read(buffer)) != -1) {
                        // 將從URL讀取的內(nèi)容寫入ZIP文件。
                        zos.write(buffer, 0, bytesRead);
                    }
                }
                zos.closeEntry();
            }
        }
    }

    /**
     * 獲取類路徑的絕對(duì)地址。
     *
     * @return 類路徑的絕對(duì)地址
     */
    public static String getTemplatePath() {
        try {
            String realPath = new ClassPathResource("").getURL().getPath();
            return URLDecoder.decode(realPath, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

3.js接收blob

/**
 * 處理Blob響應(yīng)并觸發(fā)瀏覽器下載。
 * @param {Object} res - 包含頭信息和數(shù)據(jù)的響應(yīng)對(duì)象。
 * @param {string} [name] - 下載文件的可選名稱。
 * @param {string} [type2] - Blob的可選類型。
 */
export const handleBlob = (res, name, type2) => {
  // 從提供的名稱或響應(yīng)頭中獲取文件名
  const fileName = name || (res.headers['content-disposition'] && 
                            decodeURI(res.headers['content-disposition'])
                            .split('filename=')[1]);

  // 從提供的type2或響應(yīng)頭中獲取類型
  const type = type2 || res.headers['content-type'];

  // 創(chuàng)建Blob對(duì)象
  const blob = new Blob([res.data], { type });

  // 觸發(fā)瀏覽器下載
  const downloadElement = document.createElement('a');
  downloadElement.href = window.URL.createObjectURL(blob);
  downloadElement.download = fileName; // 設(shè)置下載文件的名稱
  document.body.appendChild(downloadElement);
  downloadElement.click();
  document.body.removeChild(downloadElement);
}

4.調(diào)用

String title = "測(cè)試.zip";
BaseZipUtils.downZipFile(response, fileList, title,1);

調(diào)用結(jié)果:

Java中多目錄文件壓縮成zip

將多個(gè)文件打包到zip提供給用戶下載,抽離出來了一個(gè)工具類,支持單文件、多文件、按類型的多文件的壓縮和下載。

1.實(shí)體類

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;

    /**
     * 分類型時(shí),集合有值
     * 文件路徑集合
     */
    private List<String> urlList;
}

2.工具類

主要方法:

  • downZipListType: 允許用戶按類型將文件列表打包成zip文件進(jìn)行下載。
  • downZipList: 提供批量下載功能,可以將多個(gè)文件一起打包成zip文件。
  • downZipOne: 為單個(gè)文件提供下載功能,雖然是單個(gè)文件,但為了保持統(tǒng)一性,仍然會(huì)將其打包成zip格式。

刪除了項(xiàng)目敏感import,自行導(dǎo)入實(shí)體即可。

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("創(chuàng)建zip文件出錯(cuò)", 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("創(chuàng)建zip文件出錯(cuò)", e);
        }
    }

    /**
     * 下載單個(gè)記錄。
     */
    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("創(chuàng)建zip文件出錯(cuò)", e);
        }
    }

    /**
     * 為下載設(shè)置響應(yīng)。
     */
    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時(shí)出錯(cuò)", url, e);
                }
            }
        }
    }

    /**
     * 根據(jù)瀏覽器類型編碼文件名。
     */
    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");
    }

    /**
     * 創(chuàng)建ZipOutputStream并設(shè)置響應(yīng)頭。
     */
    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.效果

多目錄文件壓縮下載:

單文件打包下載:

到此這篇關(guān)于Java將文件壓縮成zip并下載的文章就介紹到這了,更多相關(guān)Java文件壓縮內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot內(nèi)嵌Tomcat安全漏洞修復(fù)方式

    springboot內(nèi)嵌Tomcat安全漏洞修復(fù)方式

    針對(duì)CVE-2020-1938漏洞,建議升級(jí)Tomcat至安全版本以避免受影響,影響版本包括:Apache Tomcat 9.x小于9.0.31、Apache Tomcat 8.x小于8.5.51、Apache Tomcat 7.x小于7.0.100及Apache Tomcat 6.x,
    2024-10-10
  • 一文徹底弄懂Java中MultipartFile接口和File類

    一文徹底弄懂Java中MultipartFile接口和File類

    MultipartFile是一個(gè)接口,我們可以理解為是Spring?給我們綁定的一個(gè)在使用文件上傳等時(shí)簡(jiǎn)便實(shí)現(xiàn)的口子,這篇文章主要給大家介紹了關(guān)于如何通過一文徹底弄懂Java中MultipartFile接口和File類的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • 詳解Mybatis是如何把數(shù)據(jù)庫(kù)數(shù)據(jù)封裝到對(duì)象中的

    詳解Mybatis是如何把數(shù)據(jù)庫(kù)數(shù)據(jù)封裝到對(duì)象中的

    這篇文章主要介紹了Mybatis是如何把數(shù)據(jù)庫(kù)數(shù)據(jù)封裝到對(duì)象中的,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java中的ReentrantLock實(shí)現(xiàn)原理及代碼演示

    Java中的ReentrantLock實(shí)現(xiàn)原理及代碼演示

    這篇文章主要介紹了Java中的ReentrantLock實(shí)現(xiàn)原理及代碼演示,非公平鎖 如果已經(jīng)進(jìn)入隊(duì)列,鏈表里面的線程是先進(jìn)先出,如果已經(jīng)釋放了鎖,在搶占鎖時(shí),鏈表里面的頭結(jié)點(diǎn)和還沒有入隊(duì)列的線程搶鎖,需要的朋友可以參考下
    2024-01-01
  • java自定義切面增強(qiáng)方式(關(guān)于自定義注解aop)

    java自定義切面增強(qiáng)方式(關(guān)于自定義注解aop)

    這篇文章主要介紹了java自定義切面增強(qiáng)方式(關(guān)于自定義注解aop),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java與Unix時(shí)間戳的相互轉(zhuǎn)換詳解

    Java與Unix時(shí)間戳的相互轉(zhuǎn)換詳解

    這篇文章主要為大家詳細(xì)介紹了Java與Unix時(shí)間戳的相互轉(zhuǎn)換,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • 一文帶你掌握J(rèn)ava中Scanner類的使用

    一文帶你掌握J(rèn)ava中Scanner類的使用

    Scanner類是java.util包中的一個(gè)類,常用于控制臺(tái)的輸入,當(dāng)需要使用控制臺(tái)輸入時(shí)即可調(diào)用這個(gè)類。本文將通過一些簡(jiǎn)單的例子為大家介紹一下Java中Scanner類的使用,需要的可以參考一下
    2023-04-04
  • 解決@FeignClient注入service失敗問題

    解決@FeignClient注入service失敗問題

    這篇文章主要介紹了解決@FeignClient注入service失敗問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Springboot使用切面功能詳解

    Springboot使用切面功能詳解

    Spring?Boot?是一個(gè)基于Spring框架的項(xiàng)目,它簡(jiǎn)化了基于Spring的應(yīng)用開發(fā),這篇文章主要介紹了?Spring?Boot?中的切面功能,需要的可以了解下
    2025-01-01
  • Spring MVC打印@RequestBody、@Response日志的方法

    Spring MVC打印@RequestBody、@Response日志的方法

    這篇文章主要介紹了Spring MVC打印@RequestBody、@Response日志的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-02-02

最新評(píng)論

新晃| 交城县| 台湾省| 措美县| 苍梧县| 碌曲县| 东丰县| 隆回县| 常熟市| 山丹县| 永城市| 阜新| 甘泉县| 新余市| 江津市| 丹阳市| 平顶山市| 萨嘎县| 任丘市| 河北省| 娄底市| 区。| 滁州市| 名山县| 关岭| 嘉荫县| 沿河| 通榆县| 乌拉特中旗| 嘉峪关市| 永昌县| 江永县| 新郑市| 万山特区| 三台县| 靖远县| 新乐市| 三穗县| 聂荣县| 临邑县| 灌云县|