JS文件下载的三种方式

10,630 阅读3分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战」。

前言

文件上传下载是项目中经常会遇到的常规功能,例如静态资源下载、数据导出等等。本文针文件下载总结了三种实现方法。

前端实现下载的原理一般是基于a标签下载。浏览器内部提供了钩子,而且在H5当中a标签新增了download属性。浏览器支持,当该属性的链接被点击时,浏览器会以下载文件的方式下载href的属性上的链接 这就是所谓的“钩子”。

1.文件流方式

如果后台服务器无可供下载的静态资源,一般使用文件流方式下载,不至于过多占用服务器资源,一般常用于动态的导出数据等情景。

后端返回response: image.png

代码实现

export function PostDownload (url, data) {
  return new Promise((resolve, reject) => {
    Request
      .post(url, data, {
        responseType: 'blob' // 必需
      })
      .then((res) => {
        if (res && res.status == 200) {
          reject(new Error('Download Failed'))
        } else {
          // 对后端返回的文件流处理,res.data即后端返回的文件流如上图
          const blob = new Blob([res.data])
          let filename = data.filename || `${new Date() - 0}.xlsx`;
          try {
            filename = decodeURI(res.headers['content-disposition'].split(';')[1].split('filename=')[1]);
          } catch (e) {
            console.log(e)
          }
         if (typeof window.navigator.msSaveBlob !== 'undefined') {
            	window.navigator.msSaveBlob(blob, filename);
          } else {
              const url: any = window.URL.createObjectURL(blob);
              const link = document.createElement('a');
              link.style.display = 'none';
              link.href = url;              
              link.setAttribute('download', filename);
              document.body.appendChild(link);
              link.click();
              URL.revokeObjectURL(url.href);
              document.body.removeChild(link);
              resolve()
          }
        }
      })
      .catch(() => {
        Message.error({
          message: 'Download Failed',
          duration: 2000
        })
      })
  })
}

注意事项

1)设置响应类型blob

请求头中需设置responseType:'blob',否则下载的文件将解析失败无法打开;

接口返回的完整的数据结构:

image.png

2)filename的获取方式

通过响应头Content-Disposition属性值获取下载的文件名。

Content-Disposition 响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。 注意:在响应头中,一定要后端暴露给客户端即在Access-Control-Expose-Headers里列出来,否则即使服务器在协议回包里加了该字段,客户端也只能看到无法在代码中获取到它的值。

关于Content-Disposition这里不做过多说明,点击了解更多...

image.png

2.url下载(GET方式下载)

下载的文件存储在静态资源服务器中,可以使用这种方法。后端直接返回对应资源服务器的资源url,前端直接window.location.href方式获取即可。

window.location.href="http://www.域名/template.xlsx(文件名)";
window.open(url);

3.无API浏览器直接下载

将静态资源文件直接放于 public 目录下,打包时 public 文件不会被编译。

注意:静态资源的路径,在 public 文件夹下路径是/文件名

<a class="download-file" href="/file.xlsx" download="模板.xlsx">下载模板文件</a>

或者使用非 a 标签的按钮下载:

/* 
@param {string} url  静态资源url
@param {string} filename  静态资源文件名(可选)
@param {string} target  
*/
export const fileUrlHandled = ({ url, filename, target }) => {
  const downloadElement = document.createElement('a')
  downloadElement.style.display = 'none'
  downloadElement.href = url
  if (target) {
    downloadElement.target = '_blank'
  }
  downloadElement.rel = 'noopener noreferrer'
  if (filename) {
    downloadElement.download = filename
  }
  document.body.appendChild(downloadElement)
  downloadElement.click()
  document.body.removeChild(downloadElement)
}

缺点:文件名不可控。

最后

工作中遇到的不同情境的下载,以上三种文件下载方式是工作中积累的文件下载方法的总结,如果对你有所帮助的话,帮忙点赞呀👍,你的阅读和点赞是我继续下一篇的动力,感谢看到这里的你!♥

本文著作权归原创作者翻雪所有,转载请注明出处。