跨域文件下载-前端实现

需求: 一个集成项目,从第三方平台拿到了文件地址:http://aa/videoname.mp4,前端做个点击下载的功能

  使用 a标签  <a href=' http://aa/videoname.mp4'>下载</a> 来做,  直接点击浏览器会播放此视频文件,并非所期望的下载文件.

  原因:  a标签的默认行为是链接跳转进行预览,而针对浏览无法预览的文件,也可达到下载的效果. 显然mp4是被浏览器识别了.

   a标签加上downlaod属性后(download=下载时显示的文件名),就可完成对href属性链接文件的下载,但仅是限于同源文件,如果是非同源,download属性会失效。我们本地开发时,web页面地址是localhost:8080, 即便是部署到生产环境也只是http://bb, 显然与文件地址http://aa/videoname.mp4不同源.

  使用js直接请求 http://aa/videoname.mp4进行请求到Blob再转换成本地url进行下载

1     const a = document.createElement("a");
2     a.download = fileName;
3     a.href = window.URL.createObjectURL(blob)
4     document.body.appendChild(a);
5     a.click();
6     document.body.removeChild(a)

     上面这种下载方法相当于下载了两遍, 非常慢,体验极不友好.  

  解决方案: 使用前端项目工程的代理功能,达到同源效果

  <a href=' http://aa/videoname.mp4'>

  替换为

  const fileUrl = 'http://aa/videoname.mp4'

  const downloadUrl ='/download'.concat(fileUrl) .substr(fileUrl .indexOf('/', 8)))

   <a href={downloadUrl} download={record.name}>下载</a>

 

  且在代理文件中,将带有 /download 的请求拦截,替换成真正的请求域名, 如我用的是umijs  代理配置文件/config/proxy.js:

  '/download': {
      target: "http://aa",
      changeOrigin: true,
      pathRewrite: {
        '^/download': '',
      },
      logLevel: DEV_PROXY_LOG_LEVEL,
    },

  注: 生产环境下, 这种代理是不起作用的,可以用nginx进行代理.

 

后端设置方法  设置下载请求的响应头 Content-Disposition 强制下载
这是最通用的一种方式 不受跨域和请求方式的影响

以下是一则可以触发"保存为"对话框的服务器应答:

200 OK
Content-Type: text/html; charset=utf-8
Content-Disposition: attachment; filename="cool.html"
Content-Length: 22

<HTML>Save me!</HTML>

这个简单的 HTML 文件会被下载到本地而不是在浏览器中展示。大多数浏览器默认会建议将 cool.html 作为文件名。

Content-Disposition 取值:

  inline 表示将响应内容作为页面的一部分进行展示
  attachment 表示将响应内容作为附件下载,大多数浏览器会呈现一个“保存为”的对话框
  filename(可选) 指定为保存框中预填的文件名

 

posted @ 2020-11-19 18:49  会潮  阅读(3973)  评论(0)    收藏  举报