后端代码:

@GetMapping("/{sn}")
@ApiOperation(value = "获取文件",notes = "获取文件")
public void downloadFile(@PathVariable String sn, HttpServletResponse response) throws Exception {
SysFileEntity sysFile = fileService.findBySn(sn);
if (sysFile != null){
File file = new File(sysFile.getFilePath());
if (file.exists()){
// 设置强制下载不打开
response.setContentType("application/force-download");
// 设置文件名
response.addHeader("Content-disposition", "attachment;fileName=" + URLEncoder.encode(file.getName(), StandardCharsets.UTF_8));
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
FileInputStream fis = null;
BufferedInputStream bis = null;
byte[] buffer = new byte[1024];
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream(); int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
} }
finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

前端代码:

//封装的axios
this.$http.request({
method: "get",
url: `${this.$apis.common.file}/${this.ruleForm.fileSN}`,
data: {},
//此处可以无视,前端封装全局加载遮罩
loading: false,
responseType: 'blob'
}).then(res => { const fileName = decodeURIComponent(res.headers["content-disposition"]).split("=")[1];
const _res = res.data;
let blob = new Blob([_res]);
let downloadElement = document.createElement("a");
//创建下载的链接
let href = window.URL.createObjectURL(blob);
downloadElement.href = href;
//下载后文件名
downloadElement.download = fileName;
document.body.appendChild(downloadElement);
//点击下载
downloadElement.click();
//下载完成移除元素
document.body.removeChild(downloadElement);
//释放掉blob对象
window.URL.revokeObjectURL(href); })

常见问题总结

  1. 前端接收到的响应头中不包含 “content-disposition”,但是在浏览器的网络中可以看到,这里需要后端在响应头中增加

    response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
  2. 文件名返回到前端后乱码

    此处需要在后端对文件名转码

    //StandardCharsets.UTF_8 等价于"UTF8"
    URLEncoder.encode(file.getName(), StandardCharsets.UTF_8)

    在前端文件解码

    此处是把整个 “content-disposition”响应头的内容解码后再取文件名。也可以先取文件名再解码

    decodeURIComponent(res.headers["content-disposition"])
  3. 注意自己的前端框架里封装的axios是否有返回数据的拦截处理

    我这里因为需要与后端进行身份验证所以还是用的框架内封装好的请求方法。但是需要对返回的文件数据与其他区分出来

最新文章

  1. AngularJS过滤器filter-保留小数,小数点-$filter
  2. mysql数据库表的自增主键号不规律,重新排列
  3. 老贼博客php教程从零学习PHP开始写作,顺祝新同事快乐!
  4. 部分MP4在谷歌浏览器上无法播放
  5. 梯度下降法VS随机梯度下降法 (Python的实现)
  6. duilib relativepos属性导致控件错误的bug修复
  7. IE filter & z-index bug
  8. linux内核源码结构
  9. bzoj3295
  10. NSString去掉火车和空格
  11. hdr_beg(host) 主机名开始
  12. 更改Oracle数据文件名及数据文件存放路径
  13. MySQL备份常用命令总结
  14. Spring学习笔记1——入门
  15. CRMEB 商城系统常见错误修复办法
  16. vue2.x 下载后台传过来的流文件(excel)后乱码问题
  17. 下载安装Git
  18. 性能测试四十六:Linux 从网卡模拟延时和丢包的实现
  19. VS2010:“error C2712: 无法在要求对象展开的函数中使用 __try”
  20. JS获取鼠标左(右)滑事件

热门文章

  1. AcWing 466. 回文日期
  2. IDEA控制台中文显示乱码处理
  3. python3实战之字幕vtt与字母srt的相互转换
  4. iOS越狱插件源查找及避免插件劫持
  5. 【LeetCode】856. Score of Parentheses 解题报告(Python & C++)
  6. 【LeetCode】521. Longest Uncommon Subsequence I 解题报告(Python)
  7. 1079 - Just another Robbery
  8. 使用VUE CLI3.0搭建项目vue2+scss+element简易版
  9. MySQL中视图的定义、原理--触发器
  10. 第四十九个知识点:描述在IPsec和TLS后的基本想法