我們知道 元素有 屬性,表示當前鏈接不是用來瀏覽的,而是用來下載的。它的值是一個字符串,表示用戶下載得到的文件名。可是對于 PDF 文件,瀏覽器默認打開一個新的頁面加載 PDF 文件,而不會直接下載該文件。
這時候我們需要將原來的用于下載的 url 進行轉換,轉換成一個 Blob 對象的 URL。
一、用 Blob 對象來讀寫 PDF 文件
引入 Blob 對象,用 Blob( Large 二進制大型文件) 對象來讀寫 PDF 文件。
瀏覽器原生提供 Blob() 構造函數,用來生成實例對象。
new Blob(array [, options])
Blob 構造函數接受兩個參數。第一個參數是數組,成員是字符串或二進制對象,表示新生成的 Blob 實例對象的內容;第二個參數是可選的,是一個配置對象,目前只有一個屬性 type,它的值是一個字符串,表示數據的 MIME 類型,默認是空字符串。
let htmlFragment = ['hey!'];
let myBlob = new Blob(htmlFragment, { type: 'text/html' });
上面代碼中,實例對象 包含的是字符串。生成實例的時候,數據類型指定為 text/html。
下面是另一個例子,Blob 保存 JSON 數據。
let obj = { hello: 'world' };
let blob = new Blob([JSON.stringify(obj)], { type: 'application/json' });
blob; // Blob?{size: 17, type: "application/json"}
對于 MIME 類型,需要選擇適合二進制文件流的類型,而不是普通的文本類型:(MIME 類型)
瀏覽器通常使用 MIME 類型(而不是文件擴展名)來確定如何處理 URLid可以打開pdf格式嗎,因此 Web 服務器在響應頭中添加正確的 MIME 類型非常重要。如果配置不正確,瀏覽器可能會曲解文件內容,網站將無法正常工作,并且下載的文件也會被錯誤處理。
還有一種很重要的 MIME 類型
這是應用程序文件的默認值。意思是 未知的應用程序文件 ,瀏覽器一般不會自動執行或詢問執行。瀏覽器會像對待 設置了 HTTP 頭 - 值為 的文件一樣來對待這類文件。
二、通過 URL.() 方法將 Blob 對象轉換成 url
URL.() 方法將流媒體文件生成一個 URL 字符串。這個字符串代表了 Blob 對象的 URL。
該方法生成的 URL 就像下面的樣子(以 blob: 開頭的字符串)。
blob:http://localhost:3209/28c3a781-3492-4cff-82cc-2f72a0a7f245
至此我們就拿到了 Blob 對象的 URL。
當我們拿到下載 PDF 文件的地址(url)和 PDF 文件名(name)后,先轉換成二進制文件流的 urlid可以打開pdf格式嗎,然后就可以下載該文件了。
handlePdfLink(url: string, name: string): void {
fetch(url, {
method: 'get'
})
.then(function (res) {
if (res.status !== 200) {
return res.json()

}
return res.arrayBuffer()
})
.then((blobRes) => {
// 生成 Blob 對象,設置 type 等信息
const e = new Blob([blobRes], {
type: 'application/octet-stream'
})
// 將 Blob 對象轉為 url
this.blobLink = window.URL.createObjectURL(e)
this.downloadFile(this.blobLink, name)

}).catch(err => {
console.error(err)
})
}
上面代碼中 () 將產生一段二進制數據。.()
() 接受一個 流, 并等待其讀取完成. 它返回一個 實例, 并 一個 對象。
然后將文件的MIME 類型設置為 /octet- 讓瀏覽器不會自動執行或詢問執行,裝入 Blob 對象中進行讀取文件的數據內容。
再使用 URL.() 方法,針對 Blob 對象生成一個臨時 URL,以便于某些 API 使用。這個 URL 以 blob: 開頭,表明對應一個 Blob 對象,協議頭后面是一個識別符,用來唯一對應內存里面的 Blob 對象。這一點與 data://URL(URL 包含實際數據)和 file://URL(本地文件系統里面的文件)都不一樣。
最后我們添加 元素給它裝入下載地址 url 和下載文件名 name 來下載 PDF 文件。
downloadFile(url: string, name: string): void {
if (url && url.trim()) {

let a = document.createElement('a');
a.href = url;
a.download = name || '未命名文件';
a.click();
window.URL.revokeObjectURL(this.blobLink);
} else {
this.msg.remove();
this.msg.error('文件下載路徑不能為空!');
}
}
由于每次使用 URL.() 方法,都會在內存里面生成一個 URL 實例。如果不再需要該方法生成的 URL 字符串,為了節省內存,下載完成后可以使用 URL.() 方法釋放這個實例。
歡迎寫出你的看法,一起成長!