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

SpringBoot下載文件的正確解法方式

 更新時間:2023年08月09日 09:24:39   作者:habitplus007  
這篇文章主要給大家介紹了關于SpringBoot下載文件的正確解法方式,SpringBoot是一款流行的框架,用于開發(fā)Web應用程序,在使用SpringBoot構建Web應用程序時,可能需要實現(xiàn)文件下載的功能,需要的朋友可以參考下

前言

最近遇到一個奇怪的需求,前端通過post請求下載壓縮文件,同時會傳給后端一些數(shù)據(jù),用于生成壓縮包。此時后端接口就不僅僅是生成壓縮文件流輸出給前端。而必須要有報錯能力與異常處理能力。即如果后端報錯,前端應該是下載不了文件流。

比較一般的解法

一般而言,Spring Boot生成文件流供前端下載,會直接將文件流寫入到 HttpServletResponse.getOutputStream(),然而這樣會有一個問題,無論后端如何報錯,前端都能成功下載文件,因為 status=200。即如下寫法:

@PostMapping(value = "/project/code/download")
public void downloadCode(@RequestBody TProjectInfo pf, HttpServletResponse response) {
    // 1.生成源碼文件
    // 2.壓縮文件
    // 3.設置回復的一些參數(shù)
    // 4.將壓縮文件寫入網(wǎng)絡流
    log.info("request param: {}", pf);
    OutputStream os = null;
        try {
            // 配置文件下載
            // 下載文件能正常顯示中文
            String filename = pf.getProjectName() + System.currentTimeMillis() + ".zip";
            response.setHeader("Content-Disposition", "attachment;filename=" + filename);
            response.setHeader("Content-Type", "application/octet-stream");
            response.setContentType("application/octet-stream; charset=UTF-8");
            os = response.getOutputStream();
            projectService.generateCode(pf, os);
            log.info("Download  successfully!");
        } catch (Exception e) {
            log.error("Download  failed: {}", e.getMessage());
            throw new OptErrorException(OptStatus.FAIL.code, "文件下載失敗");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
}

分析原因

因為后端直接向OutputStream寫入,會覆蓋所有異常捕獲,因此前端直接向data下取字節(jié)流數(shù)據(jù)即可。

正確解法

其實就是要后端能在錯誤時返回json數(shù)據(jù),正確下載時直接取data下取字節(jié)流即可,所以使用 ResponseEntity 返回即可。

@PostMapping(value = "/project/code/download")
public ResponseEntity<InputStreamResource> downloadCode(@RequestBody TProjectInfo pf) {
   log.info("request param: {}", pf);
   String filename = pf.getProjectName() + System.currentTimeMillis() + ".zip";
   byte[] bytes = projectService.generateCode(pf);
   ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
   HttpHeaders headers = new HttpHeaders();
   headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", filename));
   return ResponseEntity.ok()
           .headers(headers)
           .contentType(MediaType.parseMediaType("application/octet-stream"))
           .body(new InputStreamResource(bais));
}

這里的異常,使用RestExceptionAdvice統(tǒng)一處理:

@RestControllerAdvice
public class ExceptionAdvice {
    private static final Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);
    /**
     * 處理數(shù)據(jù)綁定異常
     *
     * @param bindException 數(shù)據(jù)綁定異常
     * @return 統(tǒng)一響應基本結果
     */
    @ExceptionHandler(value = BindException.class)
    public ResponseEntity<Result<Object>> handleValidateException(BindException bindException) {
        logger.error("數(shù)據(jù)綁定異常,{}", bindException.getMessage(), bindException);
        return of(HttpStatus.BAD_REQUEST, "數(shù)據(jù)綁定異常");
    }
    /**
     * 統(tǒng)一處理 405 異常
     *
     * @param exception 請求方法不支持異常
     * @return 統(tǒng)一響應結果
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public ResponseEntity<Result<Object>> handleMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
        if (exception != null) {
            logger.error("Http 405, {}", exception.getMessage(), exception);
        }
        return of(HttpStatus.METHOD_NOT_ALLOWED, "方法不被支持");
    }
    private ResponseEntity<Result<Object>> of(HttpStatus status, String msg) {
        return ResponseEntity.status(status).body(Result.builder().code(OptStatus.FAIL.code).msg(msg).build());
    }
    /**
     * 統(tǒng)一處理自定義操作錯誤異常
     *
     * @param exception 操作錯誤異常
     * @return 統(tǒng)一響應結果
     */
    @ExceptionHandler(value = OptErrorException.class)
    public ResponseEntity<Result<Object>> handleOptErrorException(OptErrorException exception) {
        return of(HttpStatus.INTERNAL_SERVER_ERROR, exception.getOptMsg());
    }
    /**
     * 統(tǒng)一處理 服務器內(nèi)部 異常
     *
     * @param e 異常
     * @return 統(tǒng)一響應結果
     */
    @ExceptionHandler(value = Throwable.class)
    public ResponseEntity<Result<Object>> handle500(Throwable e) {
        if (e != null) {
            logger.error("Http 500, {}", e.getMessage(), e);
        }
        return of(HttpStatus.INTERNAL_SERVER_ERROR, "服務器內(nèi)部未知錯誤");
    }
}

以上就是解決的全過程,可能寫得有點片面,純屬一點個人實踐中的見解。

總結

到此這篇關于SpringBoot下載文件的正確解法方式的文章就介紹到這了,更多相關SpringBoot下載文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java實時日志輸出至前臺的實現(xiàn)步驟

    Java實時日志輸出至前臺的實現(xiàn)步驟

    在Java應用程序中實現(xiàn)將實時日志輸出至前臺(如Web頁面或桌面應用程序),通常涉及到幾個關鍵組件和技術的選擇,下面將詳細介紹如何使用Java實現(xiàn)實時日志輸出至前臺,并結合具體的實現(xiàn)技術和框架來說明,需要的朋友可以參考下
    2025-10-10
  • JAVA多線程實現(xiàn)的四種方式及使用場景詳解

    JAVA多線程實現(xiàn)的四種方式及使用場景詳解

    這篇文章主要介紹了JAVA多線程實現(xiàn)的四種方式及使用場景,并舉例說明了在管理系統(tǒng)中多線程的應用場景,如數(shù)據(jù)導入導出、數(shù)據(jù)緩存更新、并發(fā)用戶操作處理、系統(tǒng)監(jiān)控和定時任務執(zhí)行,需要的朋友可以參考下
    2025-01-01
  • JdbcTemplate方法介紹與增刪改查操作實現(xiàn)

    JdbcTemplate方法介紹與增刪改查操作實現(xiàn)

    這篇文章主要給大家介紹了關于JdbcTemplate方法與增刪改查操作實現(xiàn)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者使用JdbcTemplate具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-11-11
  • java webApp異步上傳圖片實現(xiàn)代碼

    java webApp異步上傳圖片實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了java webApp異步上傳圖片實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 深入了解Java行為型設計模式之策略模式

    深入了解Java行為型設計模式之策略模式

    策略模式屬于Java-設計模式中行為模式之一,該模式定義了一系列算法,并將每個算法封裝起來,使它們可以相互替換。本文將通過示例詳細講解這一模式,需要的可以參考一下
    2022-09-09
  • Java注解詳解之@Override注解

    Java注解詳解之@Override注解

    這篇文章主要給大家介紹了關于Java注解之@Override注解的相關資料,@Override是Java中的一個注解,表示一個方法是重寫(Override)了父類中的方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2023-11-11
  • Spring中的Lifecycle接口使用與源碼分析

    Spring中的Lifecycle接口使用與源碼分析

    這篇文章主要介紹了Spring中的Lifecycle接口使用與源碼分析,LifeCycle接口定義了Spring容器的生命周期,任何被Spring管理的對象都可以實現(xiàn)該接口,需要的朋友可以參考下
    2023-05-05
  • java 替換docx文件中的字符串方法實現(xiàn)

    java 替換docx文件中的字符串方法實現(xiàn)

    這篇文章主要介紹了java 替換docx文件中的字符串方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • Java實現(xiàn)文件分割與合并

    Java實現(xiàn)文件分割與合并

    這篇文章主要介紹了Java實現(xiàn)文件分割與合并,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • RocketMQ延遲消息超詳細講解

    RocketMQ延遲消息超詳細講解

    延時消息是指發(fā)送到 RocketMQ 后不會馬上被消費者拉取到,而是等待固定的時間,才能被消費者拉取到。延時消息的使用場景很多,比如電商場景下關閉超時未支付的訂單,某些場景下需要在固定時間后發(fā)送提示消息
    2023-02-02

最新評論

灵丘县| 北流市| 九龙城区| 崇信县| 土默特右旗| 永福县| 石渠县| 专栏| 千阳县| 博湖县| 来宾市| 张家口市| 五家渠市| 丹巴县| 句容市| 旺苍县| 茶陵县| 石林| 凭祥市| 白沙| 科尔| 当涂县| 蒙自县| 新巴尔虎左旗| 吉林省| 鱼台县| 宜都市| 南丹县| 涡阳县| 沭阳县| 新平| 莱阳市| 天等县| 民权县| 潍坊市| 静海县| 平南县| 焉耆| 津南区| 华阴市| 临沂市|