前端实现Blob下载功能,后端定义文件名(Content-Disposition问题与解决)


在Web应用中,我们经常需要实现文件的下载功能。有时,这个文件可能是用户上传的,有时则可能是服务器端生成的。不论哪种情况,我们都可以利用HTTP的 Content-Disposition头信息来设定下载时的文件名。下面,我们就来看看如何在前端实现这个功能。

在实现这个功能时,前端需要通过调用接口,并通过接口请求头中的鉴权,获取到后端设置的Content-Disposition中的文件名,然后将数据流BloB化,下面分别使用xhr请求,fetch请求,axios请求进行代码示例实现下载功能。

一. 获取Content-Disposition问题与解决

在某些情况下,您可能无法直接从HTTP响应中获取Content-Disposition头,例如在使用Axios库时。默认情况下,只有六种简单响应头(Simple Response Headers)会暴露给外部:Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma
Content-Disposition并不在此列表中,因此即使服务器发送了该头,客户端也无法直接访问到它。

要解决这个问题,您需要在服务器端设置响应头Access-Control-Expose-Headers,将其值设置为允许暴露Content-Disposition头。这样,当您使用Axios库发起请求时,就可以在响应中访问到Content-Disposition头了。

二. 请求示例

1.使用xhr请求

使用原生XMLHttpRequest是实现这个功能的一种方式。下面是一段示例代码:

const xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.responseType = 'Blob';
xhr.setRequestHeader('Authorization', 'token'); // 权限验证,视情况修改
xhr.onreadystatechange = function () {
  if (this.readyState === 4 && this.status === 200) {
    const name = fileName || xhr.getResponseHeader('Content-Disposition').split('filename=')[1];

    // 支持IE浏览器
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      window.navigator.msSaveOrOpenBlob(this.response, name);
      return;
    }
    const href = window.URL.createObjectURL(this.response);
    const link = document.createElement('a');
    link.style.display = 'none';
    link.href = href;
    link.setAttribute('download', name);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }
};
xhr.send();

这段代码创建了一个新的XMLHttpRequest对象,然后打开一个到指定文件路径的连接,设置了Content-Disposition头信息,并发送了请求。

2.使用fetch请求

另一种方式是使用fetch API。这是一个更现代、更易用的网络请求方式。下面是一段示例代码:

const headers = {};
Object.assign(headers, {
  Authorization: `Bearer ${token}`
});
fetch('/path/to/your/file', {
  method: 'GET',
  headers
}).then(response => {
  let name = response.headers.get('Content-Disposition').split('filename=')[1];
  name = decodeURIComponent(name);
  // 创建一个a标签并设置href为blob的URL,然后模拟点击a标签实现下载功能
  const a = document.createElement('a');
  a.href = URL.createObjectURL(response.blob());
  a.download = name; // 后端设置的文件名
  document.body.appendChild(a);
  a.click(); // 模拟点击a标签实现下载功能
  document.body.removeChild(a); // 下载完毕后移除a标签
}).catch(error => console.error(error));

这段代码首先使用fetch API发起一个请求,然后在响应返回后,将数据流转化为一个Blob对象,接着创建一个新的a标签,设置其href为Blob对象的URL,并将文件名设置为后端设置的文件名,最后模拟点击a标签实现下载功能。

3.使用axios请求

最后,我们还可以使用axios库。这是一个基于Promise的HTTP库,可以用于浏览器和node.js。下面是一段示例代码:

axios({
  method: 'get',
  url: '/path/to/your/file',
  responseType: 'blob',
  fileName: 'yourfilename.ext' // 后端设置的文件名
})
.then(response => {
  const url = URL.createObjectURL(response.data);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'yourfilename.ext'; // 后端设置的文件名
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
})
.catch(error => console.error(error));
### 前端接收后端文件流并实现自动下载 为了实现前端接收到由后端返回的文件流并触发浏览器自动下载文件功能,可以采用基于 `axios` 发起 HTTP 请求的方式获取文件流,并利用 JavaScript 的 `Blob` API 创建文件对象。之后借助 `<a>` 标签模拟点击事件完成文件下载操作。 下面是一个完整的 Vue.js 方法用于发起请求以及处理响应中的文件流: ```javascript async function downloadFile() { try { const response = await axios({ method: 'get', url: '/api/download', // 后端提供文件流的API路径 responseType: 'blob' // 显式指定期望得到的是二进制大对象(BLOB) }); // 获取文件名可以从header中读取content-disposition字段解析出来, // 或者直接定义一个默认名称。 let filename = "default_filename"; const contentDisposition = response.headers['content-disposition']; if (contentDisposition) { const matches = /filename=([^;]+)/.exec(contentDisposition); if (matches != null && matches[1]) { filename = decodeURIComponent(matches[1].trim()); } } // 构建URL对象供<a>标签使用 const blob = new Blob([response.data]); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; // 将链接添加至DOM树以便触发click() document.body.appendChild(link); // 执行点击动作启动下载流程 link.click(); // 清理临时创建的对象防止内存泄漏 window.URL.revokeObjectURL(link.href); document.body.removeChild(link); } catch (err) { console.error(err.message || err); } } ``` 此方法适用于大多数场景下的文件下载需求,无论是文档还是图片等其他类型的文件都可按照上述逻辑进行适配调整[^1]。 对于特定 MIME 类型的支持,比如 Excel 文件,则需确保设置正确的 Content-Type 头部信息给 `Blob` 构造器,例如 `"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"` 表示 `.xlsx` 文件格式[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ts_shinian_web

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值