摘要:問題以上兩種方式,當在下載格式,或者視頻文件時,瀏覽器會直接播放該文件,而達不到直接下載的功能,此時,當下載音視頻文件時無法使用以上兩種方式。
1、通過window.open()打開新頁面下載文件
window.open(`url`, "_self")
使用場景:下載excel文件,后端提供接口,接口返回的是文件流,可以直接使用window.open(),最簡單的方式。
優點:最簡潔;
弊端:當參數錯誤時,或其它原因導致接口請求失敗,這時無法監聽到接口返回的錯誤信息,需要保證請求必須是正確的且能正確返回數據流,不然打開頁面會直接輸出接口返回的錯誤信息,體驗不好。
2、通過a標簽打開新頁面下載文件export const exportFile = (url, fileName) => { const link = document.createElement("a") const body = document.querySelector("body") link.href = url link.download = fileName // fix Firefox link.style.display = "none" body.appendChild(link) link.click() body.removeChild(link) }
通過a標簽下載的方式,同window.open()是一樣的,唯一的優點是可以自定義下載后的文件名,a標簽里有download屬性可以自定義文件名。
弊端:同window.open()方式一樣,無法監聽錯誤信息。
問題:以上兩種方式,當在下載.mp3格式,或者視頻文件時,瀏覽器會直接播放該文件,而達不到直接下載的功能,此時,當下載音視頻文件時無法使用以上兩種方式。
3、通過文件流的方式下載為了解決.mp3文件下載所帶來的問題,通過ajax請求返回Blob對象,或者ArrayBuffer對象。
(1)、獲取文件如下:通過原生ajax請求返回Blob對象
const getBlob = (url) => { return new Promise((resolve) => { const xhr = new XMLHttpRequest() xhr.open("GET", url, true) xhr.responseType = "blob" xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.response) } } xhr.send() }) }
同樣,也可以通過axios返回ArrayBuffer對象,同等作用
import axios from "axios" const getFile = url => { return new Promise((resolve, reject) => { axios({ method:"get", url, responseType: "arraybuffer" }).then(data => { resolve(data.data) }).catch(error => { reject(error.toString()) }) }) }
ArrayBuffer(又稱類型化數組)
ArrayBuffer對象用來表示通用的、固定長度的原始二進制數據緩沖區。ArrayBuffer 不能直接操作,而是要通過類型數組對象或 DataView 對象來操作,它們會將緩沖區中的數據表示為特定的格式,并通過這些格式來讀寫緩沖區的內容。
Blob(Binary Large Object): 二進制大數據對象
Blob 對象表示一個不可變、原始數據的類文件對象。Blob 表示的不一定是JavaScript原生格式的數據。File 接口基于Blob,繼承了 blob 的功能并將其擴展使其支持用戶系統上的文件。
注意:
如果下載文件是文本類型的(如: .txt, .js之類的), 那么用responseType: "text"也可以, 但是如果下載的文件是圖片, 視頻之類的, 就得用arraybuffer或blob,更多詳情請查看MDN
通過ajax請求的方式下載文件,可以解決第1、2中存在的弊端,當請求錯誤時或捕獲到錯誤信息
(2)、保存文件當獲取到文件后,這時需要保存文件
const saveAs = (blob, filename) => { if (window.navigator.msSaveOrOpenBlob) { navigator.msSaveBlob(blob, filename) } else { const link = document.createElement("a") const body = document.querySelector("body") link.href = window.URL.createObjectURL(blob) // 創建對象url link.download = filename // fix Firefox link.style.display = "none" body.appendChild(link) link.click() body.removeChild(link) window.URL.revokeObjectURL(link.href) // 通過調用 URL.createObjectURL() 創建的 URL 對象 } }
為了解決IE(ie10 - 11)和Edge無法打開Blob URL鏈接的方法,微軟自己有一套方法window.navigator.msSaveOrOpenBlob(blob, filename),打開并保存文件,以上代碼做了簡單的兼容,navigator.msSaveBlob(blob, filename)是直接保存。注意,此為非標準功能,詳情請查看相關文檔。
以下為完整代碼
const getBlob = (url) => { return new Promise((resolve) => { const xhr = new XMLHttpRequest() xhr.open("GET", url, true) xhr.responseType = "blob" xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.response) } } xhr.send() }) } const saveAs = (blob, filename) => { if (window.navigator.msSaveOrOpenBlob) { navigator.msSaveBlob(blob, filename) } else { const link = document.createElement("a") const body = document.querySelector("body") link.href = window.URL.createObjectURL(blob) // 創建對象url link.download = filename // fix Firefox link.style.display = "none" body.appendChild(link) link.click() body.removeChild(link) window.URL.revokeObjectURL(link.href) // 通過調用 URL.createObjectURL() 創建的 URL 對象 } } export const download = (url, filename = "") => { getBlob(url).then((blob) => { saveAs(blob, filename) }) }4、如何實現批量下載,且打包文件
在第3點的基礎上,如果要實現批量下載,那能做到的只是連續多次調用download方法,這樣無法批量集中的下載文件。這個時候就需要能夠對已獲取到的文件流,進行一個打包的操作,然后一次下載完畢。
這時,需要用到兩個庫jszip 和 file-saver
完整的思路,通過ajax獲取文件,然后用 jszip 壓縮文件, 再用 file-saver 生成文件
(1)、獲取文件同第3點中的第(1)點
(2)、打包文件export const download = () => { const urls = ["url", "url"] //需要下載的路徑 const zip = new JSZip() const cache = {} const promises = [] urls.forEach((item) => { const promise = getBlob(item).then((data) => { // 下載文件, 并存成ArrayBuffer對象 zip.file("下載文件名", data, { binary: true }) // 逐個添加文件 cache[item.fileName] = data }) promises.push(promise) }) Promise.all(promises).then(() => { zip.generateAsync({ type: "blob" }).then((content) => { // 生成二進制流 FileSaver.saveAs(content, `打包下載.zip`) // 利用file-saver保存文件 }) }) }
相關jszip/file-saver更多詳情
jszip:
https://github.com/Stuk/jszip
http://stuk.github.io/jszip/d...
file-saver:
https://github.com/eligrey/Fi...
貼上完整代碼
/** * 獲取文件 * @param url * @returns {Promise} */ const getBlob = (url) => { return new Promise((resolve) => { const xhr = new XMLHttpRequest() xhr.open("GET", url, true) xhr.responseType = "blob" xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.response) } } xhr.send() }) } /** * 批量打包zip包下載 * @param urlArr Array [{url: 下載文件的路徑, fileName: 下載文件名稱}] * @param filename zip文件名 */ export const download = (urlArr, filename = "打包下載") => { if (!urlArr.length > 0) return const zip = new JSZip() const cache = {} const promises = [] urlArr.forEach((item) => { const promise = getBlob(item.url).then((data) => { // 下載文件, 并存成ArrayBuffer對象 zip.file(item.fileName, data, { binary: true }) // 逐個添加文件 cache[item.fileName] = data }) promises.push(promise) }) Promise.all(promises).then(() => { zip.generateAsync({ type: "blob" }).then((content) => { // 生成二進制流 FileSaver.saveAs(content, `${filename}.zip`) // 利用file-saver保存文件 }) }) }
注意:
由于通過瀏覽器進行打包壓縮,如果文件過大,或者下載的內容過多,可能導致瀏覽器崩潰。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104340.html
摘要:沒有瀏覽器測試,所以不知道是不是有效,其實里面看起來比我寫的那個復雜,實際上多了個檢驗格式上兼容寫法所以不要怕,如果我錯了記得提醒下我啊。目前為止其實已經該說的都差不多覆蓋到了吧,動手能力強的話已經可以根據教程寫一個實例出來的了。 系列文章 關于前端上傳文件全面基礎掃盲貼(零)關于前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest關于前端上傳文件全面基礎掃盲貼(...
摘要:為了解救上面說到的問題是向提交的一個草案,旨在推出一套標準的,其基本功能是實現用對本地文件進行操作。出于安全性的考慮,該只對本地文件提供有限的訪問。 系列文章 關于前端上傳文件全面基礎掃盲貼(零)關于前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest關于前端上傳文件全面基礎掃盲貼(二) ----- File關于前端上傳文件全面基礎掃盲貼(三) ----- For...
摘要:二編輯合成照片使用編輯壓縮重設尺寸比例轉成輸出預覽。三保存并上傳照片提交數據到服務器需要服務器支持我跳過了。數據主要來自拍攝的照片,多用于移動端開發,端也會用到,此插件兼容主流瀏覽器,以下不支持。 系列文章 關于前端上傳文件全面基礎掃盲貼(零)關于前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest關于前端上傳文件全面基礎掃盲貼(二) ----- File關于前端...
摘要:狀態表示對象的狀態狀態描述未初始化。表示成功,表示未找到,表示服務器內部錯誤等。前提是瀏覽器必須支持這個功能,而且服務器端必須同意這種跨域。事件傳輸成功完成。 系列文章 關于前端上傳文件全面基礎掃盲貼(零)關于前端上傳文件全面基礎掃盲貼(一) ----- XMLHttpRequest關于前端上傳文件全面基礎掃盲貼(二) ----- File關于前端上傳文件全面基礎掃盲貼(三) ----...
閱讀 2461·2021-11-22 15:35
閱讀 3751·2021-11-04 16:14
閱讀 2685·2021-10-20 13:47
閱讀 2487·2021-10-13 09:49
閱讀 2064·2019-08-30 14:09
閱讀 2359·2019-08-26 13:49
閱讀 878·2019-08-26 10:45
閱讀 2762·2019-08-23 17:54