1. 程式人生 > 程式設計 >javascript Blob物件實現檔案下載

javascript Blob物件實現檔案下載

目錄
  • 說明
  • 一、Blob物件
  • 二、前端
  • 三、後端
  • 總結

說明

最近遇到一個需求,檔案下載,但需要鑑權,這就意味著不能用後臺返回下載連結的方式進行下載,因為一旦被別人拿到這條連結,就可以不需要任何許可權就直接下載,因此需要換種思路,在一番百度之後,瞭解到了blob物件,這就是本文要講的內容

注意:本文僅為記錄學習軌跡,如有侵權,聯絡刪除

一、Blob物件

Blob 物件表示一個不可變、原始資料的類檔案物件。它的資料可以按文字或二進位制的格式進行讀取,也可以轉換成 ReadableStream 來用於資料操作。

二、前端

blob下載思路:

1) 使用ajax發起請求,指定接收型別為blob(responseType: ‘blob')

2)讀取請求返回的頭部資訊裡的content-disposition,返回的檔名就在這裡面(或者自定義檔名,可跳過此步驟)
3)使用URL.createObjectURL將請求的blob資料轉為可下載的url地址
4)使用a標籤下載

程式碼:

// 下載
export function download(query,newFileName) {
  return request({
    url: '/file/download',method: 'get',responseType: 'blob',params: query
  }).then((res) => www.cppcns.com
{ /** * blob下載思路 * 1) 使用ajax發起請求,指定接收型別為blob(responseType: 'blob') * 2)讀取請求返回的頭部資訊裡的content-disposition,返回的檔名就在這裡面(或者自定義檔名,可跳過此步驟) * 3)使用URL.createObjectURL將請求的blob資料轉為可下載的url地址 * 4)使用a標籤下載 * */ let blob = res.data // 從response的headers中獲取filename,後端responsewww.cppcns.com
.setHeader("Content-disposition","attachment; filename=xxxx.docx") 設定的檔名; // let patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*') // let contentDisposition = decodeURI(res.headers['content-disposition']) // let result = patt.exec(contentDisposition) // let fileName = result[1] //將請求的blob資料轉為可下載的url地址 let url = URL.createObjectURL(blob) // 建立一個下載標籤<a> const aLink = document.createElement('a') aLink.href = url // 2.直接使用自定義檔名,設定下載檔名稱 aLink.setAttribute('download',newFileName ) document.body.appendChild(aLink) // 模擬點選下載 aLink.click() // 移除改下載標籤 document.body.removeChild(aLink); }) }

呼叫該方法

//下載
    download(row) {
      // filePath:檔案路徑,例如:e:\upload\
	  // fileName:檔名, 例如:a.xlsx
      let form = {
        filePath: row.filePath,fileName: row.fileName,};
      //下載,row.fileOriginalName是檔案的原始名稱,僅僅用於檔案下載時起個名字而已
      download(form,row.fileOriginalName);
    }
// 由於本人使用的是阿里的oss服務,所以只需要傳個檔案路徑回去後端,根據檔案路徑查詢oss介面得到返回的檔案流即可,例如(BufferedInputStream),在響應頭設定好返回的型別即可

三、後端

後端這裡用了阿里的oss服務,直接拿到檔案流(new BufferedInputStream(ossObject.getObjectContent())),如果是非oss的情況下,只需要讀取對應伺服器上面的檔案(File),轉成BufferedInputSt客棧ream後,直接套用下面的程式碼即可(即通過response.getOutputStream()設定BufferedOutputStream 就行了)

	// response:響應
	// filePath:檔案路徑,例如:e:\upload\
	// fileName:檔名, 例如:a.xlsx
   public void download(HttpServletResponse response,String filePath,String fileName) {
        //待下載檔名
        response.reset();
        response.setHeader("Content-Disposition","attachment;filename=" + fileName);
        response.setContentType("application/octet-stream");
        response.setChVGUTNOtizaracterEncoding("utf-8");
        // 建立OSSClient例項。
        OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);
        // ossObject包含檔案所在的儲存空間名稱、檔名稱、檔案元資訊以及一個輸入流。
        OSSObject ossObject = ossClient.getObject(bucketName,filePath + "/" + fileName);

        BufferedInputStream in = null;
        BufferedOutputStream out = null;

        byte[] buff = new byte[1024];
        int length = 0;
        try {
            in = new BufferedInputStream(ossObject.getObjectContent());
            out = new BufferedOutputStream(response.getOutputStream());
            while ((length = in.read(buff)) != -1){
                out.write(buff,length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(out != null){
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!