后台下载:获取响应头文件名

动态文件名下载实现方案

硬编码文件名的弊端

硬编码文件名在实际项目中存在明显缺陷:

  • 无法处理动态生成的文件名(如包含时间戳或服务器节点名)
  • 后端更了解导出数据的业务语义,适合由后端命名
  • 后端生成的唯一序列号可避免本地文件重名冲突
拦截器信息丢失问题

如果是已经开发完成的项目,通常Axios拦截器通常会直接返回res.data,导致响应头中的Content-Disposition字段丢失。解决方案是引入某个变量skipInterceptor配置,允许特定接口跳过拦截器处理。

核心实现步骤
  • 通常需要对拦截器做一些改造,比如:

请求封装改造

service.interceptors.response.use(
  async (response) => {
    const config = response.config;
    
    if (config.skipInterceptor) {
      return response;
    }
    
    const { data } = response;
    if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
      return data;
    }
    
    return data;
  }
);

使用示例:

文件名解析工具

function getRawFileName(header) {
  if (!header) return 'download';
  const match = header.match(/filename="?([^"]+)"?/);
  const rawName = match ? match[1] : 'download';
  try {
    return decodeURIComponent(rawName);
  } catch (e) {
    return rawName;
  }
}

业务层调用处理

const handleExport = async (payload) => {
  try {
    const res = await exportApiLogList(payload);
    
    if (res.data.type === 'application/json') {
      const text = await res.data.text();
      const errorData = JSON.parse(text);
      Message.error(errorData.msg || '导出失败');
      return;
    }
    
    const disposition = res.headers['content-disposition'] || '';
    const fileName = getRawFileName(disposition);
    
    const blob = new Blob([res.data], { type: res.data.type });
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    
    window.URL.revokeObjectURL(url);
    a.remove();
  } catch (err) {
    console.error('下载流程异常', err);
  }
};
注意事项:主要需要看的内容

跨域Headers限制
后端需在响应头中显式暴露Content-Disposition:

Access-Control-Expose-Headers: Content-Disposition

本地环境调试限制
由于浏览器策略和开发环境代理的影响,本地服务可能无法获取文件名。建议在真实测试环境或生产环境下验证。

内存管理优化
使用URL.createObjectURL创建的链接会占用内存,需手动调用window.URL.revokeObjectURL(url)释放资源。

错误处理机制
必须检查res.data.type是否为application/json,避免用户下载到错误信息文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值