背景:
之前的需求是根據接口中提供的Blob數據實現PDF下載,已實現代碼如下:
1 const url = window.URL.createObjectURL(newBlob([response.data],{type: 'application/pdf'})
2 const link = document.createElement('a') 3 link.href = url 4 let filename = response['headers']['content-disposition']?.split('filename=')[1] 5 filename = decodeURI(filename) 6 link.setAttribute('download', filename) 7 document.body.appendChild(link) 8 link.click() 9 link.remove() 10 window.URL.revokeObjectURL(link.href)
思路就是: 獲取Blob數據 => 更改Blob類型 => 轉化為Blob URL => 生成a標簽 => 設置名稱 => 完成下載 => 去除a標簽 => 釋放Blob內存
新需求:
現 PRD 需要將直接下載更改為 瀏覽器在線預覽
思路:
- 利用a標簽的href屬性, 將接收到的Blob數據轉化為Base64數據格式,並將其類型更改為PDF,代碼如下:
1 let fileReader = new FileReader(); 2 let blobData = new Blob([response.data], {type: 'application/pdf'}) 3 fileReader.readAsDataURL(blobData); 4 fileReader.onload = function(){ 5 base64Data = fileReader.result; 6 console.log('base64數據', base64Data) 7 }
此方法可以實現需求,但是在新版谷歌瀏覽器被禁止,報錯如下
Not allowed to navigate top frame to data URL:
查詢結果如下:
Chrome 禁止從頁面打開 Data URI 網址了,是出於安全考慮(釣魚方面)。 單擊這個鏈接的話,會直接報錯,Not allowed to navigate top frame to data URL Chrome 的人做了統計,說從非 Data URI 頁面跳到 Data URI 頁面的情況只有不到萬分之五的概率,如果你的網站恰巧用到了這種在前端生成頁面的方式,可以嘗試遷移到后端來生成。
- 采用插件來實現,由於使用的是react框架,所以采用了react-pdf插件,此插件地址如下:
https://www.npmjs.com/package/react-pdf
文檔說明較少,使用較簡單, 可以自定義樣式, 靈活性較高, 但樣式調整比較麻煩,而且有點點卡?
最終實現方法:
由於前兩種方法於PRD而言都有點瑕疵,最后恍然大悟,發現window.open一行代碼可輕松解決,代碼如下:
const url = window.URL.createObjectURL(newBlob([response.data],{type: 'application/pdf'})
window.open(url)
之前只是記得window.open只能打開url,沒想到Blob url也適用
Window.open() Window 接口的 open() 方法,是用指定的名稱將指定的資源加載到瀏覽器上下文(窗口 window ,內嵌框架 iframe 或者標簽 tab )。如果沒有指定名稱,則一個新的窗口會被打開並且指定的資源會被加載進這個窗口的瀏覽器上下文中。 語法 let windowObjectReference = window.open(strUrl, strWindowName, [strWindowFeatures]); strUrl === 要在新打開的窗口中加載的URL。 strWindowName === 新窗口的名稱。 strWindowFeatures === 一個可選參數,列出新窗口的特征(大小,位置,滾動條等)作為一個DOMString。
也是自己知識漏洞了. 這也是這偏隨筆的原因.
關於Blob Url:
Blob URL(參考W3C,官方名稱)或Object-URL(參考MDN和方法名稱)與Blob或File對象一起使用。 Blob URL只能由瀏覽器在內部生成。URL.createObjectURL()將創建一個特殊的Blob或File對象的引用,以后可以使用它來發布URL.revokeObjectURL()。這些URL只能在瀏覽器的單個實例中和同一個會話中(即頁面/文檔的生命周期)在本地使用。 Blob URL / Object URL是一種偽協議,允許Blob和File對象用作圖像,下載二進制數據鏈接等的URL源。 例如,不能處理Image對象的原始字節數據,因為它不知道如何處理它。它需要例如圖像(二進制數據)通過URL加載。這適用於任何需要URL作為源的東西。不用上傳二進制數據,而是通過URL提供回來,最好使用額外的本地步驟來直接訪問數據而無需通過服務器。 對於編碼為Base-64的字符串的Data-URI也是更好的選擇。Data-URI的問題是每個char在JavaScript中占用兩個字節。最重要的是,由於Base-64編碼增加了33%。Blob是純粹的二進制字節數組,它不像Data-URI那樣具有任何重要的開銷,這使得它們處理速度越來越快。
- 是一種偽協議
- 只能在瀏覽器內部生成
- 是Blob數據的唯一映射