摘要:问题以上两种方式,当在下载格式,或者视频文件时,浏览器会直接播放该文件,而达不到直接下载的功能,此时,当下载音视频文件时无法使用以上两种方式。
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保存文件 }) }) }
注意:
由于通过浏览器进行打包压缩,如果文件过大,或者下载的内容过多,可能导致浏览器崩溃。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/104340.html
摘要:没有浏览器测试,所以不知道是不是有效,其实里面看起来比我写的那个复杂,实际上多了个检验格式上兼容写法所以不要怕,如果我错了记得提醒下我啊。目前为止其实已经该说的都差不多覆盖到了吧,动手能力强的话已经可以根据教程写一个实例出来的了。 系列文章 关于前端上传文件全面基础扫盲贴(零)关于前端上传文件全面基础扫盲贴(一) ----- XMLHttpRequest关于前端上传文件全面基础扫盲贴(...
摘要:为了解救上面说到的问题是向提交的一个草案,旨在推出一套标准的,其基本功能是实现用对本地文件进行操作。出于安全性的考虑,该只对本地文件提供有限的访问。 系列文章 关于前端上传文件全面基础扫盲贴(零)关于前端上传文件全面基础扫盲贴(一) ----- XMLHttpRequest关于前端上传文件全面基础扫盲贴(二) ----- File关于前端上传文件全面基础扫盲贴(三) ----- For...
摘要:二编辑合成照片使用编辑压缩重设尺寸比例转成输出预览。三保存并上传照片提交数据到服务器需要服务器支持我跳过了。数据主要来自拍摄的照片,多用于移动端开发,端也会用到,此插件兼容主流浏览器,以下不支持。 系列文章 关于前端上传文件全面基础扫盲贴(零)关于前端上传文件全面基础扫盲贴(一) ----- XMLHttpRequest关于前端上传文件全面基础扫盲贴(二) ----- File关于前端...
摘要:状态表示对象的状态状态描述未初始化。表示成功,表示未找到,表示服务器内部错误等。前提是浏览器必须支持这个功能,而且服务器端必须同意这种跨域。事件传输成功完成。 系列文章 关于前端上传文件全面基础扫盲贴(零)关于前端上传文件全面基础扫盲贴(一) ----- XMLHttpRequest关于前端上传文件全面基础扫盲贴(二) ----- File关于前端上传文件全面基础扫盲贴(三) ----...
阅读 2459·2021-11-22 15:35
阅读 3751·2021-11-04 16:14
阅读 2684·2021-10-20 13:47
阅读 2486·2021-10-13 09:49
阅读 2062·2019-08-30 14:09
阅读 2357·2019-08-26 13:49
阅读 877·2019-08-26 10:45
阅读 2761·2019-08-23 17:54