欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:前端 a鏈接 如何實現(xiàn)下載功能

柚子快報邀請碼778899分享:前端 a鏈接 如何實現(xiàn)下載功能

http://yzkb.51969.com/

目錄

前言

標(biāo)簽 download

a 標(biāo)簽鏈接下載的實現(xiàn)

1. 整體流程

2. 實現(xiàn)步驟

3. 類圖

4. 代碼示例?

download 使用注意點

1. 同源 URL 的限制

2. 不能攜帶 Header

Blob 轉(zhuǎn)換

方法1. 用作 URL(blob:)

方法2. 轉(zhuǎn)換為 base64(data:)

兩種方法總結(jié)與對比

responseType

擴(kuò)展閱讀

1. Blob

2. URL.createObjectURL()

3. URL.revokeObjectURL()

4. FileReader.readAsDataURL()

前言

在中后臺項目中,前端難免需要處理下載的邏輯,需要下載的內(nèi)容包括但不限于圖片、Excel表格、CSV文件、MP4文件、PDF文件、TXT文件、JSON文件、HTML文件等等。雖然下載的內(nèi)容各式各樣,但是下載的原理大同小異。下面來一起學(xué)習(xí)一下前端是如何處理下載的。

標(biāo)簽 download

這應(yīng)該是最常見,最受廣大人民群眾喜聞樂見的一種下載方式了,搭配上 download 屬性, 就能讓瀏覽器將鏈接的 URL 視為下載資源,而不是導(dǎo)航到該資源。

如果 download 再指定個 filename ,那么就可以在下載文件時,將其作為預(yù)填充的文件名。不過名字中的 / 和 \ 會被轉(zhuǎn)化為下劃線 _,而且文件系統(tǒng)可能會阻止文件名中的一些字符,因此瀏覽器會在必要時適當(dāng)調(diào)整文件名。

a 標(biāo)簽鏈接下載的實現(xiàn)

1. 整體流程

為了實現(xiàn)通過a標(biāo)簽鏈接下載文件,我們需要對a標(biāo)簽的href屬性進(jìn)行設(shè)置,使其指向文件的下載鏈接。具體步驟如下表所示:

下面我們將逐步介紹每個步驟需要做的事情,并提供相應(yīng)的代碼和注釋。

2. 實現(xiàn)步驟

步驟1:創(chuàng)建一個a標(biāo)簽元素 首先,我們需要使用document.createElement方法創(chuàng)建一個a標(biāo)簽元素,并將其賦值給一個變量,以便后續(xù)操作。

// 創(chuàng)建一個a標(biāo)簽元素

const downloadLink = document.createElement('a');

步驟2:設(shè)置a標(biāo)簽的href屬性為文件的下載鏈接 接下來,我們需要將下載鏈接賦值給a標(biāo)簽的href屬性,以便瀏覽器能夠正確地下載文件。

// 設(shè)置a標(biāo)簽的href屬性為下載鏈接

downloadLink.href = ''

步驟3:設(shè)置a標(biāo)簽的download屬性,用于指定下載鏈接的默認(rèn)文件名

如果我們想要指定下載鏈接的默認(rèn)文件名,可以使用a標(biāo)簽的download屬性。這樣,當(dāng)用戶點擊下載鏈接時,瀏覽器會自動將文件以指定的文件名保存到本地。

// 設(shè)置a標(biāo)簽的download屬性為文件名

downloadLink.download = 'file.pdf'

步驟4:將a標(biāo)簽添加到HTML文檔中

我們需要將創(chuàng)建的a標(biāo)簽元素添加到HTML文檔中的某個元素中,以便用戶能夠看到下載鏈接并進(jìn)行下載操作。

// 將a標(biāo)簽添加到HTML文檔中的某個元素中

document.body.appendChild(downloadLink);

步驟5:觸發(fā)a標(biāo)簽的點擊事件,即模擬用戶點擊下載鏈接

為了觸發(fā)文件的下載,我們需要模擬用戶點擊a標(biāo)簽的行為。可以使用click方法來觸發(fā)a標(biāo)簽的點擊事件。

// 觸發(fā)a標(biāo)簽的點擊事件,即模擬用戶點擊下載鏈接

downloadLink.click();

步驟6:完成文件下載

通過以上步驟,我們已經(jīng)成功地實現(xiàn)了通過a標(biāo)簽鏈接下載文件的功能。用戶點擊下載鏈接后,瀏覽器會自動下載文件到本地。

3. 類圖

下面是本文所涉及的類的關(guān)系示意圖:

4. 代碼示例?

// 創(chuàng)建一個a標(biāo)簽元素

const downloadLink = document.createElement('a');

// 設(shè)置a標(biāo)簽的href屬性為下載鏈接

downloadLink.href = '

// 設(shè)置a標(biāo)簽的download屬性為文件名

downloadLink.download = 'file.pdf';

// 將a標(biāo)簽添加到HTML文檔中的某個元素中

document.body.appendChild(downloadLink);

// 觸發(fā)a標(biāo)簽的點擊事件,即模擬用戶點擊下載鏈接

downloadLink.click();

download 使用注意點

標(biāo)簽雖好,但還有一些值得注意的點:

1. 同源 URL 的限制

download 只在同源 URL 或 blob: 、 data: 協(xié)議起作用

也就是說跨域是下載不了的......(這種說法不全對,除非后端配置 Content-Disposition 為 attachment,后面會講)

首先,非同源 URL 會進(jìn)行導(dǎo)航操作。其次,如果非要下載,可以先將其轉(zhuǎn)換為 blob: 或 data: 再進(jìn)行下載

2. 不能攜帶 Header

使用 標(biāo)簽下載是帶不了 Header 的,因此不能通過添加請求表頭的形式來鑒權(quán),但是可以將 sessionid 或 token 字段拼接到 URL 末尾來達(dá)到鑒權(quán)的目的。這里我們給出另一個解決方案:

先發(fā)送請求獲取 blob 文件流,這樣就能在請求時進(jìn)行鑒權(quán);鑒權(quán)通過后再執(zhí)行下載操作。

這樣是不是就能很好的同時解決問題1和問題2帶來的兩個痛點了呢,而且下載的文件名也能自定義了

順便提一下,location.href 和 window.open 也存在同樣的問題。

Blob 轉(zhuǎn)換

前文介紹到,在非同源請情況下可以將資源當(dāng)成二進(jìn)制的 blob 先拿到手,再進(jìn)行 的下載處理。接下來,我們介紹兩種 blob 的操作:

方法1. 用作 URL(blob:)

URL.createObjectURL 可以給 File 或 Blob 生成一個URL,形式為 blob:/,此時瀏覽器內(nèi)部就會為每個這樣的 URL 存儲一個 URL → Blob 的映射。因此,此類 URL 很短,但可以訪問 Blob。

// 下載 Excel 方法

excel(data, fileName) {

this.download0(data, fileName, "application/vnd.ms-excel");

},

// 下載 Word 方法

word(data, fileName) {

this.download0(data, fileName, "application/msword");

},

// 下載 Zip 方法

zip(data, fileName) {

this.download0(data, fileName, "application/zip");

},

// 下載 Html 方法

html(data, fileName) {

this.download0(data, fileName, "text/html");

},

// 下載 Markdown 方法

markdown(data, fileName) {

this.download0(data, fileName, "text/markdown");

},

download0(data, fileName, mineType) {

// 創(chuàng)建 blob

let blob = new Blob([data], { type: mineType });

// 創(chuàng)建 href 超鏈接,點擊進(jìn)行下載

window.URL = window.URL || window.webkitURL;

let href = URL.createObjectURL(blob);

let downA = document.createElement("a");

downA.href = href;

downA.download = fileName;

downA.click();

// 銷毀超連接

window.URL.revokeObjectURL(href);

},

不過它有個副作用。雖然這里有 Blob 的映射,但 Blob 本身只保存在內(nèi)存中的。瀏覽器無法釋放它。

在文檔退出時(unload),該映射會被自動清除,因此 Blob 也相應(yīng)被釋放了。但是,如果應(yīng)用程序壽命很長,那這個釋放就不會很快發(fā)生。

因此,如果我們創(chuàng)建一個 URL,那么即使我們不再需要該 Blob 了,它也會被掛在內(nèi)存中。

不過,URL.revokeObjectURL 可以從內(nèi)部映射中移除引用,允許 Blob 被刪除并釋放內(nèi)存。所以,在即時下載完資源后,不要忘記立即調(diào)用 URL.revokeObjectURL。

方法2. 轉(zhuǎn)換為 base64(data:)

作為 URL.createObjectURL 的一個替代方法,我們也可以將 Blob 轉(zhuǎn)換為 base64-編碼的字符串。這種編碼將二進(jìn)制數(shù)據(jù)表示為一個由 0 到 64 的 ASCII 碼組成的字符串,非常安全且“可讀”。

更重要的是 —— 我們可以在 “data-url” 中使用此編碼。“data-url” 的形式為 data:[][;base64],。我們可以在任何地方使用這種 url,和使用“常規(guī)” url 一樣。

FileReader 是一個對象,其唯一目的就是從 Blob 對象中讀取數(shù)據(jù),我們可以使用它的 readAsDataURL 方法將 Blob 讀取為 base64。請看以下示例:

let blob = new Blob([res.data]); // res.data是后臺返回的文件

let reader = new FileReader();

reader.readAsDataURL(blob);

reader.onload = (e) => {

// 轉(zhuǎn)換完成,創(chuàng)建一個a標(biāo)簽用于下載

let a = document.createElement('a');

a.download = fileName;

a.href = e.target.result;

document.body.appendChild(a);

a.click();

document.body.removeChild(a);

}

在上述例子中,我們先實例化了一個 fileReader,用它來讀取 blob。

一旦讀取完成,就可以從 fileReader 的 result 屬性中拿到一個data: URL 格式的 Base64 字符串。

最后,我們給 fileReader 注冊了一個 onload 事件,在讀取操作完成后開始下載。

兩種方法總結(jié)與對比

URL.createObjectURL(blob) 可以直接訪問,無需“編碼/解碼”,但需要記得撤銷(revoke);

而 Data URL 無需撤銷(revoke)任何操作,但對大的 Blob 進(jìn)行編碼時,性能和內(nèi)存會有損耗。

總而言之,這兩種從 Blob 創(chuàng)建 URL 的方法都可以用。但通常 URL.createObjectURL(blob) 更簡單快捷。

responseType

export const fetchFile = async (params) => {

return axios.get(api, {

params,

responseType: "blob"

});

};

最后,我們回頭說一下請求的注意點:如果你的項目使用的是 XHR (比如 axios)而不是 fetch, 那么請記得在請求時添加上 responseType 為 'blob'。

responseType 不是 axios 中的屬性,而是 XMLHttpRequest 中的屬性,它用于指定響應(yīng)中包含的數(shù)據(jù)類型,當(dāng)為 "blob" 時,表明 Response 是一個包含二進(jìn)制數(shù)據(jù)的 Blob 對象。

除了 blob 之外,responseType 還有 arraybuffer、json、text等其他枚舉字符串值。

擴(kuò)展閱讀

1. Blob

Blob 全稱為 binary large object ,即二進(jìn)制大對象,它是 JavaScript 中的一個對象,表示原始的類似文件的數(shù)據(jù)。下面是 MDN 中對 Blob 的解釋:

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

ReadableStream?來用于數(shù)據(jù)操作。

實際上,Blob 對象是包含有只讀原始數(shù)據(jù)的類文件對象。簡單來說,Blob 對象就是一個不可修改的二進(jìn)制文件。

(1)Blob 創(chuàng)建

可以使用 Blob() 構(gòu)造函數(shù)來創(chuàng)建一個 Blob:

new Blob(array, options);

其有兩個參數(shù):

array:由?ArrayBuffer、ArrayBufferView、Blob、DOMString?等對象構(gòu)成的,將會被放進(jìn)?Blob;options:可選的?BlobPropertyBag?字典,它可能會指定如下兩個屬性

type:默認(rèn)值為 "",表示將會被放入到?blob?中的數(shù)組內(nèi)容的 MIME 類型。endings:默認(rèn)值為"transparent",用于指定包含行結(jié)束符\n的字符串如何被寫入,不常用。

常見的 MIME 類型如下:

下面來看一個簡單的例子:

const blob = new Blob(["Hello World"], {type: "text/plain"});

?這里可以成為動態(tài)文件創(chuàng)建,其正在創(chuàng)建一個類似文件的對象。這個 blob 對象上有兩個屬性:

size:Blob對象中所包含數(shù)據(jù)的大?。ㄗ止?jié));type:字符串,認(rèn)為該Blob對象所包含的 MIME 類型。如果類型未知,則為空字符串。

下面來看打印結(jié)果:

const blob = new Blob(["Hello World"], {type: "text/plain"});

console.log(blob.size); // 11

console.log(blob.type); // "text/plain"

注意,字符串"Hello World"是 UTF-8 編碼的,因此它的每個字符占用 1 個字節(jié)。

到現(xiàn)在,Blob 對象看起來似乎我們還是沒有啥用。那該如何使用 Blob 對象呢?可以使用 URL.createObjectURL() 方法將將其轉(zhuǎn)化為一個 URL,并在 Iframe 中加載:

const iframe = document.getElementsByTagName("iframe")[0];

const blob = new Blob(["Hello World"], {type: "text/plain"});

iframe.src = URL.createObjectURL(blob);

2. URL.createObjectURL()

URL.createObjectURL()?靜態(tài)方法會創(chuàng)建一個?DOMString,其中包含一個表示參數(shù)中給出的對象的 URL。這個 URL 的生命周期和創(chuàng)建它的窗口中的?document?綁定。這個新的 URL 對象表示指定的?File?對象或?Blob?對象。

備注:?此特性在?Web Worker?中可用

備注:?此特性在?Service Worker?中不可用,因為它有可能導(dǎo)致內(nèi)存泄漏。

語法

objectURL = URL.createObjectURL(object);

參數(shù)?:object:用于創(chuàng)建 URL 的?File?對象、Blob?對象或者?MediaSource?對象。

返回值?:一個DOMString包含了一個對象 URL,該 URL 可用于指定源?object的內(nèi)容。

內(nèi)存管理

在每次調(diào)用?createObjectURL()?方法時,都會創(chuàng)建一個新的 URL 對象,即使你已經(jīng)用相同的對象作為參數(shù)創(chuàng)建過。當(dāng)不再需要這些 URL 對象時,每個對象必須通過調(diào)用?URL.revokeObjectURL()?方法來釋放。

瀏覽器在 document 卸載的時候,會自動釋放它們,但是為了獲得最佳性能和內(nèi)存使用狀況,你應(yīng)該在安全的時機(jī)主動釋放掉它們。

3. URL.revokeObjectURL()

URL.revokeObjectURL()?靜態(tài)方法用來釋放一個之前已經(jīng)存在的、通過調(diào)用?URL.createObjectURL()?創(chuàng)建的 URL 對象。當(dāng)你結(jié)束使用某個 URL 對象之后,應(yīng)該通過調(diào)用這個方法來讓瀏覽器知道不用在內(nèi)存中繼續(xù)保留對這個文件的引用了。

你可以在?sourceopen?被處理之后的任何時候調(diào)用?revokeObjectURL()。這是因為?createObjectURL()?僅僅意味著將一個媒體元素的?src?屬性關(guān)聯(lián)到一個?MediaSource?對象上去。調(diào)用revokeObjectURL()?使這個潛在的對象回到原來的地方,允許平臺在合適的時機(jī)進(jìn)行垃圾收集。

備注:?此特性在?Web Worker?中可用

語法:window.URL.revokeObjectURL(objectURL);

參數(shù): 一個?objo'b'jDOMString,表示通過調(diào)用?URL.createObjectURL()?方法產(chǎn)生的 URL 對象。

返回值 undefined

4. FileReader.readAsDataURL()

readAsDataURL?方法會讀取指定的?Blob?或?File?對象。讀取操作完成的時候,readyState?會變成已完成DONE,并觸發(fā)?loadend?事件,同時?result?屬性將包含一個data:URL 格式的字符串(base64 編碼)以表示所讀取文件的內(nèi)容

語法?

readAsDataURL(blob)

?參數(shù) blob即將被讀取的?Blob?或?File?對象。

例子


Image preview...

function previewFile() {

var preview = document.querySelector("img");

var file = document.querySelector("input[type=file]").files[0];

var reader = new FileReader();

reader.addEventListener(

"load",

function () {

preview.src = reader.result;

},

false,

);

if (file) {

reader.readAsDataURL(file);

}

}

柚子快報邀請碼778899分享:前端 a鏈接 如何實現(xiàn)下載功能

http://yzkb.51969.com/

精彩文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/18894002.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄