axios get或者post请求后端文件流下载文件、读取响应头Content-Disposition获取文件名

规范化的响应头Content-Disposition

参考文章 https://blog.robotshell.org/2012/deal-with-http-header-encoding-for-file-download/

Content-Disposition: attachment;
                     filename="$encoded_fname";
                     filename*=utf-8''$encoded_fname

filename 参数:是标准的文件名传递方式,用于指定下载的文件名。它只支持 ASCII 字符,因此如果文件名包含非 ASCII 字符,需要对其进行编码。可以使用 URLEncoder.encode() 方法对文件名进行编码,并在 Content-Disposition 头字段中使用该编码后的文件名,其中 $encoded_fname 是对文件名进行编码后的值。
filename* 参数:这是文件名的扩展方式,使用了 RFC 5987 中的规范,其中 $encoded_fname 是对文件名进行 UTF-8 编码后的值。
2010年 RFC 5987 发布,正式规定了 HTTP Header 中多语言编码的处理方式采用parameter*=charset'lang'value的格式,其中:
charset 和 lang 不区分大小写。
lang 是用来标注字段的语言,以供读屏软件朗诵或根据语言特性进行特殊渲染,可以留空。
value 根据 RFC 3986 Section 2.1 使用百分号编码,并且规定浏览器至少应该支持 ASCII 和 UTF-8 。
当 parameter 和 parameter* 同时出现在 HTTP 头中时,浏览器应当使用后者。

java后端配置Content-Disposition并解决中文文件名乱码问题,经测试ie或谷歌都能正常返回中文字符
String realFileName = URLEncoder.encode(realFileName, StandardCharsets.UTF_8.toString()); 
response.setHeader("Content-Disposition", "attachment; filename=\"" + realFileName + "\"; filename*=utf-8''" + realFileName); 
疑问:filename*=utf-8''$encoded_fname不配置可以吗,我看filename="$encoded_fname"兼容性挺好的?

filename="$encoded_fname"的配置通常已经足够满足大多数情况,因为它是 Content-Disposition 头字段的标准方式来指定下载的文件名。大多数现代浏览器都能正确地处理这种情况,并且它具有良好的兼容性。
虽然filename*=utf-8''$encoded_fname提供了更好的支持,特别是对于包含非 ASCII 字符的文件名,但并不是所有的客户端都能正确解析这种方式。
因此,如果你只关心基本的兼容性,filename="$encoded_fname"已经足够了。

相应java后端配置
String realFileName = URLEncoder.encode(realFileName, StandardCharsets.UTF_8.toString()); 
response.setHeader("Content-Disposition", "attachment; filename=\"" + realFileName + "\""); 

所以综上,实际开发的话,前端取第一个filename即可

前端下载文件流并读取响应头中content-disposition字段作为文件名

      const res = await axios({
        method: 'get',
        url: `/exportData`,
        params: {
          id: this.id,
        },
        responseType: 'blob',
      });
      //  post请求
      //  const res = await http({
      //  method: 'post',
      //  url: `/exportData`,
      //  data: {
      //    id: this.id,
      //  },
      //  responseType: 'blob',
      //  });
      if(!res.data) return
      // 获取响应头Content-Disposition中的filename参数,后端需要设置
      // content-disposition格式示例:
      // "filename=不合格情况统计.xlsx"; filename*=utf-8''不合格情况统计.xlsx"
      const fileNameEncode = res.headers['content-disposition']
        .split('filename=')[1]
        .split(';')[0];
      const fileName = decodeURI(fileNameEncode, 'utf-8').replaceAll('"', '');
      const blob = new Blob([res.data]);
      const url = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.style.display = 'none';
      link.setAttribute('href', url);
      link.setAttribute('download', fileName);
      link.click();
      URL.revokeObjectURL(url);
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值