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

spring文件下載的四種方式及對比分析

 更新時間:2025年08月13日 09:40:31   作者:言不由衷煦  
本文對比spring文件下載的四種方式,每種方式結(jié)合實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

方式一:通過ResponseEntity 方式來下載

@ApiOperation(value = "下載數(shù)據(jù)文檔模板")
@GetMapping("/download-template/1")
public ResponseEntity<Resource> downloadFile01(HttpServletRequest request) {
    try {
        Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
        // 檢查資源是否存在
        if (resource.exists() || resource.isReadable()) {
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodeFileName(request, resource.getFilename()))
                    .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
                    .body(resource);
        } else {
            return ResponseEntity.notFound().build();
        }
    } catch (Exception e) {
        log.error("文件模板下載失??!", e);
        return ResponseEntity.internalServerError().build();
    }
}
/**
 * 根據(jù)瀏覽器類型編碼文件名
 * @param request 請求對象
 * @param fileName 原始文件名
 * @return 編碼后的文件名
 */
private static String encodeFileName(HttpServletRequest request, String fileName) {
    String userAgent = request.getHeader("User-Agent");
    // 處理IE及Edge瀏覽器
    if (userAgent.contains("MSIE") || userAgent.contains("Trident") || userAgent.contains("Edge")) {
        return cn.hutool.core.net.URLEncoder.createDefault().encode(fileName, StandardCharsets.UTF_8);
    }
    // 其他瀏覽器使用ISO-8859-1編碼
    return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}

方式二:通過ResponseEntity 方式來下載

@ApiOperation(value = "下載數(shù)據(jù)文檔模板")
@GetMapping("/download-template/2")
public ResponseEntity<StreamingResponseBody> downloadFile02(HttpServletRequest request) {
    try {
        Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
        StreamingResponseBody body = outputStream -> {
            FileUtil.writeToStream(resource.getFile(), outputStream);
        };
        // 檢查資源是否存在
        if (resource.exists() || resource.isReadable()) {
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()))
              			//	省略 encodeFileName 方法
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodeFileName(request, resource.getFilename()))
                    .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
                    .body(body);
        } else {
            return ResponseEntity.notFound().build();
        }
    } catch (Exception e) {
        log.error("文件模板下載失?。?, e);
        return ResponseEntity.internalServerError().build();
    }
}

方式三:通過Servlet原生下載

@ApiOperation(value = "下載數(shù)據(jù)文檔模板")
@GetMapping("/download-template/3")
public void downloadFile03(HttpServletRequest request, HttpServletResponse response) throws IOException {
    Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
    // 設(shè)置響應(yīng)頭
    response.setContentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM).toString());
    response.setHeader("Content-Disposition", "attachment; filename=" + encodeFileName(request, resource.getFilename()));
  	//	這里是關(guān)鍵,如果設(shè)置 response.setContentLength() 則下載的文件只能是 50 多兆
    response.setContentLengthLong(resource.contentLength());
    FileUtil.writeToStream(resource.getFile(), response.getOutputStream());
}

方式四:通過ResponseEntity<byte[]> 方式來下載

@ApiOperation(value = "下載數(shù)據(jù)文檔模板")
@GetMapping("/download-template/4")
public ResponseEntity<byte[]> downloadFile04(HttpServletRequest request, HttpServletResponse response) throws IOException {
    try {
        Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
        // 檢查資源是否存在
        if (resource.exists() || resource.isReadable()) {
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodeFileName(request, resource.getFilename()))
                    .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
                    .body(FileUtil.readBytes(resource.getFile()));
        } else {
            return ResponseEntity.notFound().build();
        }
    } catch (Exception e) {
        log.error("文件模板下載失敗!", e);
        return ResponseEntity.internalServerError().build();
    }
}

四種下載方式的對比

1、核心特性對比

方式內(nèi)存占用適用場景流式支持資源管理代碼復(fù)雜度
ResponseEntity<byte[]>高(全量加載)小文件(<10MB)如配置文件、圖片?自動釋放內(nèi)存低(簡單封裝)
ResponseEntity<Resource>中(按需加載)動態(tài)資源(如JAR內(nèi)文件、數(shù)據(jù)庫Blob)?(需手動關(guān)閉流)需顯式關(guān)閉InputStream中(需處理流)
ResponseEntity<StreamingResponseBody>極低(分塊傳輸)超大文件(視頻、日志等)?(自動分塊)自動處理流生命周期高(需分塊邏輯)
Servlet原生下載低(手動控制)需要精細(xì)控制響應(yīng)頭/流的場景?(手動實現(xiàn))需手動關(guān)閉流高(冗余代碼)

2、典型場景推薦

  • 快速小文件下載‌:優(yōu)先使用ResponseEntity<byte[]>,直接返回字節(jié)數(shù)組,無需流控制。
  • 動態(tài)資源或加密文件‌:選擇ResponseEntity<Resource>,靈活處理輸入流。
  • ‌**超大文件(GB級)**‌:必須用StreamingResponseBody分塊傳輸,避免OOM。
  • 兼容舊系統(tǒng)或特殊需求‌:Servlet原生下載(如需要自定義響應(yīng)頭邏輯)

完整的代碼

import cn.hutool.core.io.FileUtil;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
 * description
 *
 * @author lijin
 * @since 2025-08-12 14:05
 */
@Slf4j
@Controller
@RequestMapping("/cycle-data/document01")
public class DownloadController {
    @ApiOperation(value = "下載數(shù)據(jù)文檔模板")
    @GetMapping("/download-template/1")
    public ResponseEntity<Resource> downloadFile01(HttpServletRequest request) {
        try {
            Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
            // 檢查資源是否存在
            if (resource.exists() || resource.isReadable()) {
                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodeFileName(request, resource.getFilename()))
                        .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
                        .body(resource);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            log.error("文件模板下載失?。?, e);
            return ResponseEntity.internalServerError().build();
        }
    }
    @ApiOperation(value = "下載數(shù)據(jù)文檔模板")
    @GetMapping("/download-template/2")
    public ResponseEntity<StreamingResponseBody> downloadFile02(HttpServletRequest request) {
        try {
            Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
            StreamingResponseBody body = outputStream -> {
                FileUtil.writeToStream(resource.getFile(), outputStream);
            };
            // 檢查資源是否存在
            if (resource.exists() || resource.isReadable()) {
                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodeFileName(request, resource.getFilename()))
                        .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
                        .body(body);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            log.error("文件模板下載失??!", e);
            return ResponseEntity.internalServerError().build();
        }
    }
    @ApiOperation(value = "下載數(shù)據(jù)文檔模板")
    @GetMapping("/download-template/3")
    public void downloadFile03(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
        // 設(shè)置響應(yīng)頭
        response.setContentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM).toString());
        response.setHeader("Content-Disposition", "attachment; filename=" + encodeFileName(request, resource.getFilename()));
        response.setContentLengthLong(resource.contentLength());
        FileUtil.writeToStream(resource.getFile(), response.getOutputStream());
    }
    @ApiOperation(value = "下載數(shù)據(jù)文檔模板")
    @GetMapping("/download-template/4")
    public ResponseEntity<byte[]> downloadFile04(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            Resource resource = new ClassPathResource("templates/ubuntu-20.04.6-desktop-amd64.iso");
            // 檢查資源是否存在
            if (resource.exists() || resource.isReadable()) {
                return ResponseEntity.ok()
                        .header(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()))
                        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + encodeFileName(request, resource.getFilename()))
                        .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM))
                        .body(FileUtil.readBytes(resource.getFile()));
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            log.error("文件模板下載失?。?, e);
            return ResponseEntity.internalServerError().build();
        }
    }
    /**
     * 根據(jù)瀏覽器類型編碼文件名
     * @param request 請求對象
     * @param fileName 原始文件名
     * @return 編碼后的文件名
     */
    private static String encodeFileName(HttpServletRequest request, String fileName) {
        String userAgent = request.getHeader("User-Agent");
        // 處理IE及Edge瀏覽器
        if (userAgent.contains("MSIE") || userAgent.contains("Trident") || userAgent.contains("Edge")) {
            return cn.hutool.core.net.URLEncoder.createDefault().encode(fileName, StandardCharsets.UTF_8);
        }
        // 其他瀏覽器使用ISO-8859-1編碼
        return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
    }
}

到此這篇關(guān)于spring文件下載的四種方式及對比分析的文章就介紹到這了,更多相關(guān)spring文件下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Spring的RPC通訊模型的使用與比較

    基于Spring的RPC通訊模型的使用與比較

    這篇文章主要介紹了基于Spring的RPC通訊模型的使用與比較,詳細(xì)的介紹了RMI、Caucho的Hessian和Burlap以及Spring自帶的HTTP invoker,感興趣的可以了解一下
    2018-09-09
  • Java如何獲取Date的“昨天”與“明天”示例代碼

    Java如何獲取Date的“昨天”與“明天”示例代碼

    最近在做項目的時候用到Date和Calendar比較多,而且用到的方式也比較全,突然想到一個問題,Java如何獲取Date的"昨天"與"明天",也就是前一天和后一天呢?思考后寫出了方法,想著萬一以后用到,就總結(jié)出來,也方便有需要的朋友們參考借鑒,下面來一起看看吧。
    2016-12-12
  • SpringBoot+Redis實現(xiàn)數(shù)據(jù)字典的方法

    SpringBoot+Redis實現(xiàn)數(shù)據(jù)字典的方法

    這篇文章主要介紹了SpringBoot+Redis實現(xiàn)數(shù)據(jù)字典的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • IDEA修改生成jar包名字的兩種方法實現(xiàn)

    IDEA修改生成jar包名字的兩種方法實現(xiàn)

    本文主要介紹了IDEA修改生成jar包名字的兩種方法實現(xiàn),通過簡單的步驟,您可以修改項目名稱并在打包時使用新的名稱,具有一定的參考價值,感興趣的可以了解下
    2023-08-08
  • 使用idea將工具類打包使用的詳細(xì)教程

    使用idea將工具類打包使用的詳細(xì)教程

    這篇文章主要介紹了使用idea將工具類打包使用的詳細(xì)教程,本文通過圖文并茂給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 簡單了解JAVA內(nèi)存區(qū)域效果知識

    簡單了解JAVA內(nèi)存區(qū)域效果知識

    這篇文章主要介紹了簡單了解JAVA內(nèi)存區(qū)域效果知識,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • SpringDataJpa的@Query注解報錯的解決

    SpringDataJpa的@Query注解報錯的解決

    這篇文章主要介紹了SpringDataJpa的@Query注解報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • springboot bean循環(huán)依賴實現(xiàn)以及源碼分析

    springboot bean循環(huán)依賴實現(xiàn)以及源碼分析

    最近在使用Springboot做項目的時候,遇到了一個循環(huán)依賴的 問題,所以下面這篇文章主要給大家介紹了關(guān)于springboot bean循環(huán)依賴實現(xiàn)以及源碼分析的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • 基于SpringCloudGateway實現(xiàn)微服務(wù)網(wǎng)關(guān)的方式

    基于SpringCloudGateway實現(xiàn)微服務(wù)網(wǎng)關(guān)的方式

    Spring?Cloud?Gateway是Spring?官方基于Spring?5.0,Spring?Boot?2.0和Project?Reactor?等技術(shù)開發(fā)的網(wǎng)關(guān),旨在為微服務(wù)架構(gòu)提供一種簡單而有效的統(tǒng)一的API路由管理方式,對SpringCloudGateway實現(xiàn)微服務(wù)網(wǎng)關(guān)相關(guān)知識感興趣的朋友一起看看吧
    2021-12-12
  • spring boot2.0總結(jié)介紹

    spring boot2.0總結(jié)介紹

    今天小編就為大家分享一篇關(guān)于spring boot2.0總結(jié)介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12

最新評論

平利县| 武宁县| 博湖县| 宁远县| 新巴尔虎右旗| 山阳县| 清丰县| 昆山市| 镇远县| 旅游| 潜山县| 南江县| 渭南市| 盈江县| 商城县| 云阳县| 台江县| 澄江县| 搜索| 囊谦县| 裕民县| 渭南市| 铜梁县| 浦东新区| 南乐县| 张家川| 文水县| 禹州市| 塘沽区| 乳山市| 北票市| 成都市| 乾安县| 延川县| 昌江| 奉新县| 伽师县| 松原市| 上杭县| 北票市| 政和县|