跨境派

跨境派

跨境派,专注跨境行业新闻资讯、跨境电商知识分享!

当前位置:首页 > 卖家故事 > 前端文件下载方法总结

前端文件下载方法总结

时间:2024-03-30 19:11:04 来源:网络cs 作者:峨乐 栏目:卖家故事 阅读:

标签: 方法  总结  文件 
阅读本书更多章节>>>>

前端文件下载方法总结

1、open或location.href

最简单最直接的方式,跟a标签访问下载链接一样
前提:下载地址不需要鉴权 以及 不存在跨域问题

window.location.href = url // url为下载地址window.open('downloadFile.zip');

优点:简单方便

缺点:

直接访问可能会覆盖当前页面地址不能添加header,也就不能进行鉴权会出现URL长度限制问题需要注意url编码问题浏览器可直接浏览的文件类型是不提供下载的,如txt、png、jpg、gif、pdf等无法知道下载的进度

2、用a标签下载

a标签可以访问下载文件的地址。如果 是对于浏览器可以直接浏览的文件类型:jpg\png\gif\txt等,a标签不能直接下载。

所以,在html5中,a标签提供了 download属性。

简单用法:

<a href="example.jpg" download>点击下载</a>//如果带属性值 指定下载的文件名,即重命名下载文件。不设置的话默认是文件原本名。<a href="example.jpg" download="test">点击下载</a>

动态a标签:
下面的url即文件或接口的地址
如需要额外参数,通过url后问号拼接参数,后端get请求方式接收

服务端需要配置url资源的响应头Content-disposition值为attachment,浏览器识别会调用下载弹窗,进一步配置filename值即下载的默认文件名。

// 封装function downloadFile (url, name) {  url = url || ''  name = name || ''  let ele = document.createElement('a')  ele.target = '_blank'  ele.href = url  ele.download = name  ele.click()  ele = null}// 调用downloadFile(url)

判断浏览器是否支持download属性:

const isSupport = 'download' in document.createElement('a');

需要注意一些信息:

Edge 13在尝试下载data url链接时会崩溃。Chrome 65及以上版本只支持同源下载链接。Firefox只支持同源下载链接。

基于上面描述,如果你尝试下载跨域链接,那么其实download的效果就会没了,跟不设置download表现一致。即浏览器能预览的还是会预览,而不是下载。

对于在跨域下不能下载可浏览的文件,得跟后端协商,在后端层做多一层转发,最终返回给前端的文件链接跟下载页同域。

优点:download属性能解决不能直接下载浏览器可浏览的文件

缺点:

不能下载跨域下的浏览器可浏览的文件不能进行鉴权url资源或接口响应头配置了filename时,前端无法自定义下载文件名。有兼容性问题,特别是IE前端需要自定义展示下载进度条需求时无法支持。

3、利用Blob下载,发送ajax请求api获取文件流进行下载

这种方法除了能利用已知文件地址路径进行下载外,还适用于需要调取API获取文件流下载的形式。
有些时候后端不会直接提供一个下载地址给你直接访问,而是要调api。

方法:

前端请求接口设置responseType: 'blob', 统一 转为Blob 数据,然后利用URL.createObjectUrl生成url地址,赋值在a标签的href属性上,结合download进行下载.

blob 是 js 里表示二进制文件的对象。

target.response就是一个Blob对象,打印出来会看到两个属性size和type。

2种方法代码参考

文件下载方法参考,第二种可设置下载进度。
参考:https://blog.csdn.net/u010059669/article/details/122623034

/** * 第一种方法: * @param {String} path - 下载地址/下载请求地址。 * @param {String} name - 下载文件的名字/重命名(考虑到兼容性问题,最好加上后缀名) */downloadFile (path, name) {    const xhr = new XMLHttpRequest();    xhr.open('get', path);    xhr.responseType = 'blob';    xhr.send();    xhr.onload = function () {        if (this.status === 200 || this.status === 304) {            // 如果是IE10及以上,不支持download属性,采用msSaveOrOpenBlob方法,但是IE10以下也不支持msSaveOrOpenBlob            if ('msSaveOrOpenBlob' in navigator) {                navigator.msSaveOrOpenBlob(this.response, name);                return;            }            // const blob = new Blob([this.response], { type: xhr.getResponseHeader('Content-Type') });            // const url = URL.createObjectURL(blob);            const url = URL.createObjectURL(this.response);            const a = document.createElement('a');            a.style.display = 'none';            a.href = url;            a.download = name;            document.body.appendChild(a);            a.click();            document.body.removeChild(a);            URL.revokeObjectURL(url);        }    };}/** * 第二种方法: * @description: ajax下载/导出文件 * @param {string} url 资源或接口地址,可携带参数 * @param {function} progressCallback 选填,前端自定义的下载进度回调 */function downloadFromApi (url, progressCallback) {  return new Promise((resolve, reject) => {    const xhr = new XMLHttpRequest()    xhr.open('get', url)    xhr.responseType = 'blob'    xhr.onload = e => {      if (xhr.status === 200) {        const response = xhr.response        resolve(response)        const dispoition = xhr.getResponseHeader('Content-Disposition') || ''        const nameStr = dispoition.split(';')[1] || ''        const fileName = decodeURIComponent(nameStr.split('=')[1] || '')        if (window.navigator.msSaveOrOpenBlob) {          // 兼容处理,ie下的blob下载          window.navigator.msSaveOrOpenBlob(response, fileName)        } else {          const href = URL.createObjectURL(response)  let ele = document.createElement('a')  ele.target = '_blank'  ele.href = href  ele.download = fileName  ele.click()  ele = null  URL.revokeObjectURL(href)        }      } else {        reject(new Error(`${xhr.status}:请求失败`))      }    }    xhr.error = err => {      reject(err)    }    xhr.onprogress = e => {      if (e.lengthComputable) {        const percentComplete = e.loaded / e.total        progressCallback && progressCallback(percentComplete)      }    }    xhr.send(null)  })}

下载进度设置的原理

服务端需要配置响应头的Content-Length,值为文件大小(未配置的话会在文件传输完成后才弹窗提示下载,响应感知太慢)。

前端监听xhr对象的progress事件:

xhr.onprogress = e => {  if (e.lengthComputable) {    const percentComplete = e.loaded / e.total    // 打印当前已完成的进度比例    console.log(percentComplete)  }}

另一种封装方式(axios 请求)

如果是封装了axios请求,可以在调请求后,使用下面的封装的downLoadFile 方法,使用示例:

/*httpRequest: 封装的下载API请求,记得设置responseType = 'blob'url: 接口*/ httpRequest(url).then(async (res) => {   console.log('下载请求返回:', res);   const { data, response } = res;   if (data && response.status === 200) {   // 调用封装好的下载文件的方法     downLoadFile(data, response);   }  }).catch(async (err) => {   console.log(err); }); /** * 下载文件 * @param {any} data - 下载请求返回blob对象的data, 打印出来会有一个size和type 属性。 * @param {Response} response- 请求的response */const downLoadFile = (data: any, response: Response) => {  let contentType = response.headers.get('content-type') || undefined;  let contentDisposition = response.headers.get('content-disposition') || undefined;  contentType = isExistValue(contentType) ? contentType : undefined;  contentDisposition = isExistValue(contentDisposition) ? contentDisposition : undefined;// 文件名提取  let filename = 'xxx';  if (typeof contentDisposition === 'string') {    contentDisposition = valueToLowerCase(contentDisposition);    try {      // 文件名提取      filename = contentDisposition.match(/filename=(.*)/)[1];    } catch (err) {      console.log(err);      // @ts-ignore      filename = contentDisposition;    }  }  // 创建一个 Blob 对象  const blob = new Blob([data], { type: contentType });  // @ts-ignore  if (typeof window.navigator.msSaveBlob !== 'undefined') {    // 兼容IE,window.navigator.msSaveBlob:以本地方式保存文件    window.navigator.msSaveBlob(blob, decodeURI(filename));  } else {    const href = window.URL.createObjectURL(blob);    const eLink = document.createElement('a'); // 创建一个<a>标签    eLink.style.display = 'none'; // 隐藏标签    eLink.href = href; // 配置href,指向本地文件的内存地址    eLink.download = decodeURI(filename);    document.body.appendChild(eLink);    eLink.click();    // 释放URL 对象    document.body.removeChild(eLink);    // 释放掉blob对象    URL.revokeObjectURL(href);  }};

图片预览

如果是图片预览,也是后端返回的地址,需要带上token去请求。需要用到base64。伪代码参考思路:

const [imgSrc, setImgSrc] = useState('');// 图片预览的srcuseEffect(() => { const url = 'xxx.xx.xx/img/wx.png';  // httpRequest自己封装的axios请求 , responseType 为 'blob'  httpRequest(url).then(async (res) => {    console.log('下载返回:', res);    const { data, response } = res;    if (data && response.status === 200) {      // 生成图片预览的src      const src = await blobToBase64(data);      setImgSrc(src);    }  });}, []);/** * Blob 图像对象预览 * */const blobToBase64 = (file: Blob) => {  return new Promise((resolve, reject) => {    const reader = new FileReader();    reader.readAsDataURL(file);    reader.onload = () => resolve(reader.result);    reader.onerror = (error) => reject(error);  });};// 在Image标签中使用:<Image width="80%" alt={name} src={imgSrc} />

优点:

能解决不能直接下载浏览器可浏览的文件可添加鉴权信息

缺点: 兼容性问题,IE10以下不可用

阅读本书更多章节>>>>

本文链接:https://www.kjpai.cn/gushi/2024-03-30/151120.html,文章来源:网络cs,作者:峨乐,版权归作者所有,如需转载请注明来源和作者,否则将追究法律责任!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

文章评论