2.前端下載各種類型文件

1. 使用a標(biāo)簽的download屬性,下載所有類型文件:(Blob對(duì)象)

import axios from 'axios' //引入axios
export const download = (fileUrl, name)=> { // 下載文件地址和名稱
    //  console.log(fileUrl, name)
     //一、直接下載
    // window.location.href = fileUrl  //在地址欄上出入U(xiǎn)RL即可觸發(fā)瀏覽器的下載功能(不符合需求)
    // window.open(fileUrl) //同上,不符合需求
    // 二、直接下載(使用a標(biāo)簽download屬性) (先將圖片轉(zhuǎn)成base64)
        // var image = new Image()
        // image.setAttribute('crossOrigin', 'anonymous')
        // image.onload = function() {
        //     var canvas = document.createElement('canvas')
        //     canvas.width = image.width
        //     canvas.height = image.height
        //     var context = canvas.getContext('2d')
        //     context.drawImage(image, 0, 0, image.width, image.height)
        //     var url = canvas.toDataURL('image/png') // 得到圖片的base64編碼數(shù)據(jù)
        //     var a = document.createElement('a') // 生成一個(gè)a元素
        //     var event = new MouseEvent('click') // 創(chuàng)建一個(gè)單擊事件
        //     a.download = name || 'photo' // 設(shè)置圖片名稱
        //     a.href = url // 將生成的URL設(shè)置為a.href屬性
        //     a.dispatchEvent(event) // 觸發(fā)a的單擊事件
        // }
        // image.src = fileUrl


    //三、使用a標(biāo)簽的download屬性,下載任意類型的文件、
    // {注意:1.解決亂碼問(wèn)題,type指定文件類型
    //       2.Blob([res.data]:傳入的是res.data;而不是res
    //       3.responseType指定為blob對(duì)象}
    axios({
        method: "GET",   // "POST"
        url: fileUrl,
        responseType: "blob",   //【重點(diǎn):設(shè)置返回?cái)?shù)據(jù)類型,這里一定要設(shè)置,否則下載下來(lái)的文件會(huì)是空白】
        }).then(res => {
            downloadToFile(res,name)
          //downloadFileByReader(res,name)
        })
}

function downloadToFile(res,fileName){
        var downloadUrl = window.URL.createObjectURL(new Blob([res.data],{type:res.data.type}))
        var a = document.createElement('a')
        a.style.display = 'none'
        a.href = downloadUrl
        a.download = fileName
        //創(chuàng)建一個(gè)點(diǎn)擊事件,并傳遞給a
        var event = new MouseEvent('click')
        a.dispatchEvent(event)
}

// readAsDataURL() 方法會(huì)讀取指定的 Blob 或 File 對(duì)象。讀取操作為異步操作,當(dāng)讀取完成時(shí),
//可以從onload回調(diào)函數(shù)中通過(guò)實(shí)例對(duì)象的result屬性獲取data:URL格式的字符串(base64編碼),
// 此字符串即為讀取文件的內(nèi)容,可以放入a標(biāo)簽的href屬性中
function downloadFileByReader(res,fileName){
      const reader = new FileReader()
      // 傳入被讀取的blob對(duì)象
      reader.readAsDataURL(res.data)
      // 讀取完成的回調(diào)事件
      reader.onload = (e) => {
          let a = document.createElement('a')
          a.download = fileName
          a.style.display = 'none'
          // 生成的base64編碼
          let url = reader.result
          a.href = url
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)
      }
}

注意問(wèn)題:

1.跨域圖片能正常裁剪(圖片未轉(zhuǎn)化成base64),應(yīng)該滿足三個(gè)條件:
  1. img元素中設(shè)置crossorigin屬性
  2. 圖片允許跨域,設(shè)置響應(yīng)頭Access-Control-Allow-Origin
  3. 使用js方式請(qǐng)求圖片資源, 需要避免使用緩存,設(shè)置url后加上時(shí)間戳,或者h(yuǎn)ttp頭設(shè)置Cache-Control為no-cache

主要原因是:

  1. 如果使用跨域的資源畫(huà)到canvas中,并且資源沒(méi)有使用CORS去請(qǐng)求,canvas會(huì)被認(rèn)為是被污染了, canvas可以正常展示,但是沒(méi)辦法使用toDataURL()或者toBlob()導(dǎo)出數(shù)據(jù),見(jiàn)Allowing cross-origin use of images and canvas。 所以通過(guò)在img標(biāo)簽上設(shè)置crossorigin,啟用CORS,屬性值為anonymous,在CORS請(qǐng)求時(shí)不會(huì)發(fā)送認(rèn)證信息,見(jiàn)HTML attribute: crossorigin。
  2. 在啟用CORS請(qǐng)求跨域資源時(shí),資源必須允許跨域,才能正常返回,最簡(jiǎn)單的方式設(shè)置響應(yīng)頭Access-Control-Allow-Origin
  3. 圖片已經(jīng)通過(guò)img標(biāo)簽加載過(guò),瀏覽器默認(rèn)會(huì)緩存下來(lái),下次使用js方式再去請(qǐng)求,直接返回緩存的圖片,如果緩存中的圖片不是通過(guò)CORS請(qǐng)求或者響應(yīng)頭中不存在Access-Control-Allow-Origin,都會(huì)導(dǎo)致報(bào)錯(cuò)。
    readAsDataURL 和 createObjectURL 對(duì)比
2. readAsDataURL (blob) 和 createObjectURL (blob) 的區(qū)別:
readAsDataURL (blob) createObjectURL (blob)
返回值 可以得到一段base64的字符串 得到的是當(dāng)前文件的一個(gè)內(nèi)存url
內(nèi)存 js垃圾回收機(jī)制自動(dòng)從內(nèi)存中清理 存在于當(dāng)前document內(nèi),清除方式通過(guò)revokeObjectURL()手動(dòng)清除
執(zhí)行方式 通過(guò)回調(diào)的方式f返回,異步執(zhí)行 直接返回,同步執(zhí)行
多個(gè)文件 同時(shí)處理多個(gè)文件時(shí),需要一個(gè)文件對(duì)應(yīng)一個(gè)FileReader對(duì)象 依次返回,沒(méi)有影響
優(yōu)勢(shì)對(duì)比 可直接轉(zhuǎn)為base64格式,直接用于業(yè)務(wù) 得到本地內(nèi)存容器的URL地址,方便預(yù)覽,需要注意手動(dòng)釋放內(nèi)存的問(wèn)題,性能優(yōu)秀
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容