前端使用功能:前端直接请求后端流下载文件

        最近,项目中遇到一个前端下载文件时文件名称由后端提供的小需求(原来是前端把文件名称写死)。我们的项目架构是SpringBoot+React(TypeScript)。我看了一下后端代码,在设置响应的header已经塞进去文件名称。前端只需要从响应的header获取文件名称即可。后端设置响应header代码如下:

... ... 
try {
    fileName = new String(fileName.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
    log.error("该文件[{}]不支持此编码转换,异常消息:[{}]", fileName, e.getMessage());
}
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
... ... 

        插一句题外话,为什么要对文件名称进行“ISO8859-1”格式编码,而且还在响应header中Content-Disposition这种格式的文件名称。原因是,我们原来写的项目不是前后端分离,前端直接一个ajax请求去下载,浏览器会认识这个Content-Disposition属性,自动配置“filename=”的名称。而且需要是使用“ISO8859-1”格式编码,不然中午会乱码。但是我们现在的项目是前后端分离。每次下载文件是前端去请求后端,拿到数据后,模拟一次点击下载,返回给用户。

        我们知道了在响应的header中有文件名称,我们就需要获取响应的header。但是我这里遇到一个问题:代码获取响应的header为空,但是浏览器F12可以看到响应的header。经过一番定位与查找。发现是因为浏览器跨域问题,配置参数缺少的问题。具体解决如下(java跨域配置类):

...  ... 
//哪些header可以作为响应的一部分暴露给外部
res.setHeader("Access-Control-Expose-Headers", "*");
...  ... 

        解决以上问题后,前端可以正常获取文件名称。但是又遇到了文件名称中文乱码的问题。经过一番尝试,将文件名称解析成正常中文,具体处理如下(TypeScript前端代码):

let fileName;
const disposition = response.headers.get('Content-Disposition');
if (disposition === undefined || disposition == null) {
    fileName = '出错了';
} else {
    fileName = decodeURI(escape(response.headers.get('Content-Disposition').split(';')[1].split('filename=')[1]));
}

        完整前端代码如下:

/**
 * 文件下载
 *
 *
 * @param response
 * @param mimeEnum
 */
export function downLoadFileNew(response: any, mimeEnum: MimeEnum) {

  let fileName;
  const disposition = response.headers.get('Content-Disposition');
  if (disposition === undefined || disposition == null) {
    fileName = '出错了';
  } else {
    fileName = decodeURI(escape(response.headers.get('Content-Disposition').split(';')[1].split('filename=')[1]));
  }
  const blob = new Blob([response], {type: mimeEnum});
  const a = document.createElement('a');
  a.download = fileName;
  a.href = window.URL.createObjectURL(blob);
  a.click();
};


/**
 *
 * Mime枚举
 */
export enum MimeEnum {
  ZIP = 'application/zip',
  JPEG = "image/jpeg",
  PNG = "image/png",
  PDF = 'application/zip',
  DOC = "application/msword",
  DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  XLS = "application/vnd.ms-excel",
  XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  PPT = "application/vnd.ms-powerpoint",
  PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation",
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
前端请求后端下载文件有几种方法,其中包括使用原生servlet的HttpServletResponse方式下载使用Spring的ResponseEntity方式下载使用原生ajax之XMLHttpRequest方式下载使用jQuery的Ajax方式下载以及使用原生ajax之fetch方式下载。具体方法的实现可以参考以下资料: - 原生servlet的HttpServletResponse方式下载:通过设置response对象的响应头信息,将文件写入到响应中,然后前端通过a标签的href属性进行文件下载。参考资料中的"一. 普通文件下载"部分。 - Spring的ResponseEntity方式下载:在后端使用ResponseEntity将文件作为响应体返回,前端通过ajax请求获取文件,并使用Blob对象创建URL进行文件下载。参考资料中的"一.2 Spring的ResponseEntity方式下载"部分。 - 原生ajax之XMLHttpRequest方式下载:通过XMLHttpRequest发送请求,设置responseType为"blob",获取到文件使用Blob对象创建URL进行文件下载。参考资料中的"三. 文件下载-原生ajax之XMLHttpRequest"部分。 - jQuery的Ajax方式下载:通过$.ajax发送请求,设置dataType为"binary",获取到文件使用Blob对象创建URL进行文件下载。参考资料中的"四. 文件下载-jQuery的Ajax"部分。 - 原生ajax之fetch方式下载使用fetch发送请求,设置responseType为"blob",获取到文件使用Blob对象创建URL进行文件下载。参考资料中的"五. 下载数据库中保存的文件"部分。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hanxiaozhang2018

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

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

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

打赏作者

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

抵扣说明:

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

余额充值