前端下载文件


前言

前端业务开发中,经常会遇到下载图片、文件等需求。前端需要拿到二进制流才能进行下载操作。

二进制流

在前后端交互中,二进制流可能是一个文件或者图片以流的形式传递。

前端核心实现下载功能有:

  1. <a href="xxx" downlaod="filname"></a>
  2. window.open()
  3. form表单提交
  4. ajax请求接口,处理文件流转为blob格式

在实际业务中,根据实际接口和URL具体情况,制定具体的实现方案


一、a标签 + download属性

适用场景:

  • fileUrl是【同源】的
  • Get请求
  • 不能设置请求头,不能携带token等验证身份信息

非适用异常场景:

  • 对于非同源URL,比如协议不一致,例如当前访问页面协议是https,而fileUrl是http协议地址,浏览器会拦截下载请求(在fileUrl同时支持http和https协议时,前端也可转换一下fileUrl协议)。
  • 对于非同源URL,协议一致,但是比如第三方链接:腾讯云图片链接,即使设置了download属性,在某些浏览器异常表现是:下载文件的同时会自动变更当前访问地址。
// 已知fileUrl, fileName
const a = document.createElement("a");
document.body.appendChild(a);
a.setAttribute("style", "display:none");
a.setAttribute("href", fileUrl);
a.setAttribute("download", fileName);  // 关键属性
a.click();
URL.revokeObjectURL(fileUrl);

二、window.open(url, “_blank”)

原理和a标签类似,也是适用于Get请求

三、form表单

使用场景:

  • POST\GET请求
  • 需要携带较多参数
  • 可以设置请求头,携带token等验证信息
const downLoadForm = ({ formData, url }) => {
    let formStr = `<form action="${url}" method="post" id="sendAll" target="_self">`;
    for (let k in formData) {
        formStr += `<input type="hidden" value="${formData[k]}" name="${k}" />`
    }
    formStr += `</form>`;
    const body = document.querySelector('body');
    const container = document.createElement('div');
    container.innerHTML = formStr;
    body.append(container);
    document.querySelector('#sendAll').submit();
    container.remove();
}

四、接口请求 + blob + a标签+ download属性

适用场景:

  • POST\GET请求
  • 要下载第三方(腾讯云)图片地址,可以让后端提供统一的下载接口,拿到文件流,前端通过blob接收解析,再用a标签下载
  • 可以设置请求头,携带token等验证用户信息
// axios定义接口方法downloadImg
export const downloadImg = (params) => {
  // 设置 responseType: 'blob'
  return axios.post(api.downloadImg, null, { params, responseType: 'blob' });
}

downloadImg({url}).then(data => {
    const blob = new Blob([data], {type: data.type});  // 关键代码
    const objectUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    document.body.appendChild(a);
    a.setAttribute("style", "display:none");
    a.setAttribute("href", objectUrl);
    a.setAttribute("download", fileName);
    a.click();
    URL.revokeObjectURL(objectUrl);
}).catch(err => {
    console.log('err', err)
})

下载涉及的HTTP协议 header字段

Content-Type: application/octet-stream
  • Content-Length (用来指明发送给接收方的消息主体的大小,即用十进制数字表示的八位元组的数目。)
  • Content-Disposition( 响应头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。)
Content-Disposition: attachment;filename=test.xlsx;filename*=UTF-8

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值