天天看點

Spring boot + Vue axios 檔案下載下傳

後端代碼:

@GetMapping("/{sn}")
    @ApiOperation(value = "擷取檔案",notes = "擷取檔案")
    public void downloadFile(@PathVariable String sn, HttpServletResponse response) throws Exception {
        SysFileEntity sysFile = fileService.findBySn(sn);
        if (sysFile != null){
            File file = new File(sysFile.getFilePath());
            if (file.exists()){
                // 設定強制下載下傳不打開
                response.setContentType("application/force-download");
                // 設定檔案名
                response.addHeader("Content-disposition", "attachment;fileName=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8));
                response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
                FileInputStream fis = null;
                BufferedInputStream bis = null;
                byte[] buffer = new byte[1024];
                try {
                    fis = new FileInputStream(file);
                    bis = new BufferedInputStream(fis);
                    OutputStream os = response.getOutputStream();

                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer, 0, i);
                        i = bis.read(buffer);
                    }

                }
                finally {
                    if (bis != null) {
                        try {
                            bis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (fis != null) {
                        try {
                            fis.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
           

前端代碼:

//封裝的axios
this.$http.request({
        method: "get",
        url: `${this.$apis.common.file}/${this.ruleForm.fileSN}`,
        data: {},
		//此處可以無視,前端封裝全局加載遮罩
        loading: false,
        responseType: 'blob'
      }).then(res => {

        const fileName = decodeURIComponent(res.headers["content-disposition"]).split("=")[1];
        const _res = res.data;
        let blob = new Blob([_res]);
        let downloadElement = document.createElement("a");
        //建立下載下傳的連結
        let href = window.URL.createObjectURL(blob);
        downloadElement.href = href;
        //下載下傳後檔案名
        downloadElement.download = fileName;
        document.body.appendChild(downloadElement);
        //點選下載下傳
        downloadElement.click();
        //下載下傳完成移除元素
        document.body.removeChild(downloadElement);
        //釋放掉blob對象
        window.URL.revokeObjectURL(href);

      })
           

常見問題總結

  1. 前端接收到的響應頭中不包含 “content-disposition”,但是在浏覽器的網絡中可以看到,這裡需要後端在響應頭中增加
    response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
               
  2. 檔案名傳回到前端後亂碼

    此處需要在後端對檔案名轉碼

    //StandardCharsets.UTF_8 等價于"UTF8"
    URLEncoder.encode(file.getName(), StandardCharsets.UTF_8)
               

    在前端檔案解碼

    此處是把整個 “content-disposition”響應頭的内容解碼後再取檔案名。也可以先取檔案名再解碼

    decodeURIComponent(res.headers["content-disposition"])
               
  3. 注意自己的前端架構裡封裝的axios是否有傳回資料的攔截處理

    我這裡因為需要與後端進行身份驗證是以還是用的架構内封裝好的請求方法。但是需要對傳回的檔案資料與其他區分出來

Spring boot + Vue axios 檔案下載下傳

本文來自部落格園,作者:懷瑾于輕,轉載請注明原文連結:https://www.cnblogs.com/hjyq/p/15832674.html