" />

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

javascript Blob對(duì)象實(shí)現(xiàn)文件下載

 更新時(shí)間:2021年12月23日 10:28:28   作者:最強(qiáng)菜鳥  
這篇文章主要為大家介紹了vue組件通信的幾種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

說明

最近遇到一個(gè)需求,文件下載,但需要鑒權(quán),這就意味著不能用后臺(tái)返回下載鏈接的方式進(jìn)行下載,因?yàn)橐坏┍粍e人拿到這條鏈接,就可以不需要任何權(quán)限就直接下載,因此需要換種思路,在一番百度之后,了解到了blob對(duì)象,這就是本文要講的內(nèi)容

注意:本文僅為記錄學(xué)習(xí)軌跡,如有侵權(quán),聯(lián)系刪除

一、Blob對(duì)象

Blob 對(duì)象表示一個(gè)不可變、原始數(shù)據(jù)的類文件對(duì)象。它的數(shù)據(jù)可以按文本或二進(jìn)制的格式進(jìn)行讀取,也可以轉(zhuǎn)換成 ReadableStream 來用于數(shù)據(jù)操作。

二、前端

blob下載思路:

1) 使用ajax發(fā)起請(qǐng)求,指定接收類型為blob(responseType: ‘blob')
2)讀取請(qǐng)求返回的頭部信息里的content-disposition,返回的文件名就在這里面(或者自定義文件名,可跳過此步驟)
3)使用URL.createObjectURL將請(qǐng)求的blob數(shù)據(jù)轉(zhuǎn)為可下載的url地址
4)使用a標(biāo)簽下載

代碼:

// 下載
export function download(query,newFileName) {
  return request({
    url: '/file/download',
    method: 'get',
    responseType: 'blob',
    params: query
  }).then((res) => {
    /**
     * blob下載思路
     * 1) 使用ajax發(fā)起請(qǐng)求,指定接收類型為blob(responseType: 'blob')
     * 2)讀取請(qǐng)求返回的頭部信息里的content-disposition,返回的文件名就在這里面(或者自定義文件名,可跳過此步驟)
     * 3)使用URL.createObjectURL將請(qǐng)求的blob數(shù)據(jù)轉(zhuǎn)為可下載的url地址
     * 4)使用a標(biāo)簽下載
     * 
     */
    let blob = res.data
    // 從response的headers中獲取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 設(shè)置的文件名;
    // let patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
    // let contentDisposition = decodeURI(res.headers['content-disposition'])
    // let result = patt.exec(contentDisposition)
    // let fileName = result[1]

    //將請(qǐng)求的blob數(shù)據(jù)轉(zhuǎn)為可下載的url地址
    let url = URL.createObjectURL(blob)
    // 創(chuàng)建一個(gè)下載標(biāo)簽<a>
    const aLink = document.createElement('a')
    aLink.href = url
    // 2.直接使用自定義文件名,設(shè)置下載文件名稱
    aLink.setAttribute('download', newFileName )
    document.body.appendChild(aLink)
    // 模擬點(diǎn)擊下載
    aLink.click()
    // 移除改下載標(biāo)簽
    document.body.removeChild(aLink);
  })
}

調(diào)用該方法

//下載
    download(row) {
      // filePath:文件路徑,例如:e:\upload\
	  // fileName:文件名, 例如:a.xlsx
      let form = {
        filePath: row.filePath,
        fileName: row.fileName,
      };
      //下載,row.fileOriginalName是文件的原始名稱,僅僅用于文件下載時(shí)起個(gè)名字而已
      download(form, row.fileOriginalName);
    }
// 由于本人使用的是阿里的oss服務(wù),所以只需要傳個(gè)文件路徑回去后端,根據(jù)文件路徑查詢oss接口得到返回的文件流即可,例如(BufferedInputStream),在響應(yīng)頭設(shè)置好返回的類型即可

三、后端

后端這里用了阿里的oss服務(wù),直接拿到文件流(new BufferedInputStream(ossObject.getObjectContent())),如果是非oss的情況下,只需要讀取對(duì)應(yīng)服務(wù)器上面的文件(File),轉(zhuǎn)成BufferedInputStream后,直接套用下面的代碼即可(即通過response.getOutputStream()設(shè)置BufferedOutputStream 就行了)

	// response:響應(yīng)
	// 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.setCharacterEncoding("utf-8");
        // 創(chuàng)建OSSClient實(shí)例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // ossObject包含文件所在的存儲(chǔ)空間名稱、文件名稱、文件元信息以及一個(gè)輸入流。
        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,0,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();
            }
        }
    }

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

最新評(píng)論

卢龙县| 绥德县| 额敏县| 枞阳县| 阿鲁科尔沁旗| 黎川县| 信阳市| 海安县| 哈密市| 项城市| 雷山县| 九江市| 德令哈市| 吉首市| 海淀区| 靖宇县| 衡阳县| 辽中县| 兴化市| 珠海市| 八宿县| 江川县| 无锡市| 平潭县| 当雄县| 永川市| 平罗县| 科尔| 香港| 大丰市| 嘉兴市| 宁海县| 温泉县| 丰宁| 永兴县| 开平市| 淮北市| 贵溪市| 吐鲁番市| 聂拉木县| 南雄市|