這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前端涉及到的檔案下載還是很多應用場景的,那么前端檔案下載有多少種方式呢?每種方式有什么優缺點呢?下面就來一一介紹,
1. 使用 a 標簽下載
通過a
標簽的download
屬性來實作檔案下載,這種方式是最簡單的,也是我們比較常用的方式,先來看示例代碼:
<a href="http://www.baidu.com" download="baidu.html">下載</a>
就上面的這個示例,我們點擊下載,發現是跳轉到了百度的首頁,并沒有真的下載檔案,
因為a
標簽下載只能下載同源
的檔案;如果是跨域
的檔案,比如圖片、音視頻等媒體檔案等都無法使用上面的a
標簽方式下載,
上面的代碼是直接通過書寫a
標簽來實作檔案下載;我們也可以通過js
來實作,代碼如下:
const a = document.createElement('a') a.href = 'http://www.baidu.com' a.download = 'baidu.html' a.click()
效果和上面的一樣,都是跳轉到百度的首頁,沒有下載檔案,
這里的重點是a
標簽的download
屬性,這個屬性是HTML5
新增的,
它的作用是指定下載的檔案名,如果不指定,那么下載的檔案名就會根據請求內容的Content-Disposition
來確定,如果沒有Content-Disposition
,那么就會使用請求的URL
的最后一部分作為檔案名,
2. 使用 window.open 下載
上面使用a
標簽的案例也可以通過window.open
來實作,效果是一樣的,代碼如下:
window.open('http://www.baidu.com', '_blank')
這里的_blank
是指定用瀏覽器新視窗打開鏈接;如果不指定,那么就會在當前頁面打開,
同樣a
標簽的download
屬性也是可以使用的,代碼如下:
window.open('http://www.baidu.com', '_blank', 'download=baidu.html')
當然這種方式也是有缺陷的,對比于a
標簽,window.open
方式不能下載.html
、.htm
、.xml
、.xhtml
等檔案;因為這些檔案會被當成html
檔案來處理,所以會直接在當前頁面打開,
同樣也不能下載跨域
的檔案,這個是window.open
實作下載原理決定的,
3. 使用 location.? 下載
以下可以實作頁面跳轉的屬性,都可以實作檔案下載
3.1 location.href
// 這個方式和window.open是一樣的 location.href = 'http://www.baidu.com'
這種方式擁有window.open
的所有缺陷,所以不推薦使用,這里只當作了解,所以不做過多的講解,
3.2 location.assign
location.assign('http://www.baidu.com')
3.3 location.replace
location.replace('http://www.baidu.com')
3.4 location.reload
location.reload('http://www.baidu.com')
location.reload
是有點特殊的,它的作用是重新加載當前頁面,但是它也可以接受一個引數,這個引數就是要跳轉的頁面,所以也可以實作檔案下載,
當然同location.href
一樣,這些方式的缺點都一樣,同時還有屬于每個屬性自身的特性,這里只當拓展知識,不做過多的講解,
4. XMLHttpRequest
這種方式就是我們常說的ajax
下載,包括Axios
、Fetch
等,代碼如下:
const xhr = new XMLHttpRequest() xhr.open('GET', 'http://www.baidu.com') xhr.send() xhr.onload = function () { const blob = new Blob([xhr.response], { type: 'text/html' }) const a = document.createElement('a') a.href = URL.createObjectURL(blob) a.download = 'baidu.html' a.click() }
這里關于XMLHttpRequest
相關的知識就不做展開了,只講和檔案下載相關的部分,
上面代碼主要的邏輯是當我們的請求成功后,我們會拿到回應體Response
,這個Response
就是我們要下載的內容,
然后我們把它轉換成Blob
物件,通過URL.createObjectURL
來創建一個URL
,最后使用a
標簽的download
屬性來實作檔案下載,
5.1 Blob 物件
下面是MDN
對Blob
物件的定義:
Blob
物件表示一個不可變、原始資料的類檔案物件,
Blob
的資料可以按文本或二進制的格式進行讀取,也可以轉換成ReadableStream
來用于資料操作,
Blob
表示的不一定是JavaScript
原生格式的資料,
File
介面基于Blob
,繼承了Blob
的功能并將其擴展以支持用戶系統上的檔案,
Blob
物件是html5
新增的物件,它的作用是用來存盤二進制資料的,比如圖片、視頻、音頻等,它的使用方法如下:
/** * @param {Array} array 二進制資料 * @param {Object} options 配置項 * @param {String} options.type 檔案型別,它代表了將會被放入到 blob 中的陣列內容的 MIME 型別, * @param {String} options.endings 用于指定包含行結束符\n的字串如何被寫入,默認為transparent,表示不會修改行結束符,還可以指定為native,表示會將\n轉換為\r\n, */ const blob = new Blob([], { type: '' })
Tips:需要關注的是type
屬性,默認情況下, Blob
物件是沒有type
屬性的,那么這個Blob
就是一個無型別的Blob
,檔案不會損毀,但是無法被正常識別,
5.2 URL.createObjectURL
下面是MDN
對 URL.createObjectURL
方法的定義:
URL.createObjectURL()
靜態方法會創建一個DOMString
,其中包含一個表示引數中給出的物件的URL
,
這個URL
的生命周期和創建它的視窗中的document
系結,
這個新的URL
物件表示指定的File
物件或Blob
物件,
這個方法是用來創建一個URL
的,它的作用是把一個Blob
物件轉換成一個URL
,這個URL
可以用來下載檔案,也可以用來預覽檔案,代碼如下:
const url = URL.createObjectURL(blob)
這里需要注意的是,這個URL
的生命周期和創建它的視窗中的document
系結,
也就是說,當我們的document
被銷毀后,這個URL
就會失效,所以我們需要在合適的時機銷毀它,
代碼如下:
URL.revokeObjectURL(url)
回到我們剛才下載的問題,我們是通過Blob
物件來解決,但是我們的type
屬性是寫死的,如果在檔案型別是確定的情況下是沒問題的,
但是如果這個介面就是下載檔案的介面,檔案可能是各種型別的,我們應該怎么處理?
這里的沒有正確答案,第一個可以和介面提供者進行協商,協商方案是不確定的;第二就是通過Response
的header
來獲取檔案的type
,也是我們要講的:
const type = response.headers['content-type'] const blob = new Blob([response.data], { type })
這里我們通過Response
的header
來獲取type
,然后再創建Blob
物件,這樣就可以正確的下載檔案了,
其實content-type
也可能是application/octet-stream
,這個時候我們就需要通過file-type
來獲取檔案的type
了,
下面的代碼是通過file-type
來獲取檔案的type
:
import {fileTypeFromStream} from 'file-type'; const type = await fileTypeFromStream(response.body); const blob = new Blob([response.data], { type })
5. 總結
上面的方案這么多,其實最侄訓是落到a
標簽上,所以不管是通過瀏覽器的內置行為進行下載,還是通過ajax
進行下載,檔案下載的最侄訓是瀏覽器的行為,
本文轉載于:
https://juejin.cn/post/7254143696483991611
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/557052.html
標籤:Html/Css
上一篇:基于分步表單的實踐探索
下一篇:返回列表