跨域文件下载-前端实现
需求: 一个集成项目,从第三方平台拿到了文件地址: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(可选) 指定为保存框中预填的文件名

浙公网安备 33010602011771号