记一次前端文件下载处理过程

Axios 请求拦截处理

TypeScript 复制代码
  // 响应拦截器
  instance.interceptors.response.use(async (response: AxiosResponse<customRes, any>): Promise<any> => {
    // 文件流处理
    if (response.config.responseType == "blob") return Promise.resolve(response);
  
    return Promise.resolve(response.data);
  }, responseErrorHandle)

当响应的数据类型是文件流(Blob)时,拦截器直接返回了一个包含 response 的 Promise,以便在调用这个接口的地方能够获取到文件流并进一步处理。

请求方法处理

通过 Axios 请求文件流(Blob)并进行文件下载的函数。

请求服务器返回的文件流数据,并通过浏览器的下载机制将其保存到本地文件。

设置响应类型为 Blob 是为了告知服务器返回的数据是二进制流,方便后续在客户端进行文件下载。

TypeScript 复制代码
  /**
   * 返回文件流测试
   */
  export const getFile = () => {
    instance.get('/test/file/stream', {
      responseType: "blob", // 设置响应类型为blob
      params: {}
    }).then((response) => {
      // 处理下载文件
      const url = window.URL.createObjectURL(new Blob([response.data]));
      const link = document.createElement("a");
      link.href = url;
      link.setAttribute("download", getFileNameFromHeaders(response)); // 设置下载的文件名和扩展名
      link.click();
    })
  }

从headers中取出文件名方法封装

TypeScript 复制代码
  // 文件名处理
  export const getFileNameFromHeaders = (response: AxiosResponse) => {
    // 从响应头中获取Content-Disposition信息
    const contentDisposition = response.headers['content-disposition'];
  
    // 使用正则表达式匹配文件名
    const match = /filename="(.*)"/.exec(contentDisposition);
  
    // 获取匹配的文件名
    return match ? decodeURI(match[1]) : 'unknown'
  }
  1. instance.get('/test/file/stream', {...})
    • 使用 Axios 的 get 方法向服务器端发送 GET 请求,请求的地址是 '/test/file/stream'。
  2. responseType: "blob"
    • 在请求配置中设置 responseType 为 "blob",表示期望服务器响应的数据是二进制数据(Blob 对象)。
  3. .then((response) => {...})
    • 使用 Promise 的 .then 处理请求成功的回调函数,response 包含了从服务器返回的 Blob 对象。
  4. window.URL.createObjectURL(new Blob([response.data]))
    • 通过 window.URL.createObjectURL 创建一个临时的 URL,该 URL 表示了从服务器返回的 Blob 对象的内容。这个 URL 通常用于创建下载链接。
  5. const link = document.createElement("a");
    • 创建一个 <a> 元素,用于模拟文件下载。
  6. link.href = url;
    • 将刚刚创建的 URL 赋值给 <a> 元素的 href 属性。
  7. link.setAttribute("download", getFileNameFromHeaders(response));
    • 设置 <a> 元素的 download 属性为从服务器响应头中获取的文件名。这里使用 getFileNameFromHeaders 的函数,它可能用于从响应头中获取文件名,确保文件名包含在 Content-Disposition 头中。
  8. link.click();
    • 模拟点击 <a> 元素,触发文件下载。

整个流程的目的是通过 Axios 请求获取服务器端返回的文件流,然后使用 Blob 对象创建一个临时的 URL,并通过创建 <a> 元素模拟点击以触发文件下载。

网络服务处理

返回文件流的接口

JavaScript 复制代码
  // 服务端返回文件流,并将文件名通过 attachment 返回
  router.get('/file/stream', async (ctx, next) => {
      const filePath = path.join(__dirname, '../upload/file/测试表格.xlsx');
      // 设置响应头,告诉浏览器文件名
      ctx.attachment(encodeURI('测试表格.xlsx'));
      // 读取文件流并设置为响应体
      ctx.body = await fs.createReadStream(filePath);
  })

跨域配置

允许前端访问 Content-Disposition

JavaScript 复制代码
app.use(cors({
    exposeHeaders: ['Content-Disposition'],
    credentials: true,  // 允许携带cookies
}));

总结

服务端返回文件流,并将文件名通过 attachment 返回,文件名会被携带在 Content-Disposition中。

前端通过 getFileNameFromHeaders 方法取出 文件名

前端通过 window.URL.createObjectURL(new Blob([response.data])) 创建一个可用于浏览器中的文件下载的 URL

相关推荐
重庆穿山甲4 分钟前
Java开发者的大模型入门:AgentScope Java组件全攻略(二)
前端·后端
我爱吃土豆11199 分钟前
从零到上架:Chrome 新标签页生产力扩展 FocusTab
前端·产品
敲代码的约德尔人9 分钟前
我在 3 个项目中踩坑后,才真正理解了 JavaScript 设计模式
前端·javascript
子淼81211 分钟前
Kali Linux 入门指南:基础操作与常用指令解析
前端
Highcharts.js11 分钟前
Highcharts时间线图(Timeline Chart)完全指南:事件序列的可视化叙事图表
javascript·信息可视化·数据分析·highcharts·图表开发·时间线图表
QYR市场调研19 分钟前
低密度聚乙烯市场竞争格局变化趋势
前端
2601_9491465325 分钟前
短信通知HTTP接口开发规范:基于RESTful/HTTP协议的短信API调用实现方案
网络协议·http·restful
学以智用25 分钟前
Vue 3 组件完全指南
前端·vue.js
重庆穿山甲27 分钟前
Java开发者的大模型入门:AgentScope Java组件全攻略(一)
前端·后端
LawrenceLan31 分钟前
36.Flutter 零基础入门(三十六):StatefulWidget 与 setState 进阶 —— 动态页面必学
开发语言·前端·flutter·dart