一。JSP 式样的
public HttpServletResponse download(String path, HttpServletResponse response) {
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
// 取得文件的后缀名。
String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return response;
}
二。前后端下载代码的逻辑:
如果后台返回的是文件地址,那么前端直接通过 window.location.href 加文件地址,就可以下载文件;
但是如果后台返回的是文件流,那么前端就需要做一些处理;
其实前端处理的核心:就是将文件流转为文件,然后再模拟点击,实现前者的效果。
。
前端:
const blob = new Blob([res], {
// 设置返回的文件类型
// type: 'application/pdf;charset=UTF-8' 表示下载文档为pdf,如果是word则设置为msword,excel为excel
type: type
})
// 这里就是创建一个a标签,等下用来模拟点击事件
const a = document.createElement('a')
// 兼容webkix浏览器,处理webkit浏览器中href自动添加blob前缀,默认在浏览器打开而不是下载
const URL = window.URL || window.webkitURL
// 根据解析后的blob对象创建URL 对象
const herf = URL.createObjectURL(blob)
// 下载链接
a.href = herf
// 下载文件名,如果后端没有返回,可以自己写a.download = '文件.pdf'
a.download = filename
document.body.appendChild(a)
// 点击a标签,进行下载
a.click()
// 收尾工作,在内存中移除URL 对象
document.body.removeChild(a)
window.URL.revokeObjectURL(herf)
}</pre>
这里用简单的问题:遇到了四个问题:
1.主机被迫连接中断,捕捉异常处理
2.vue 超时处理
3.reset 问题。
4.getOutputStream() has already been called for this response的解决方法,值为空,modelAndView,@ResponseBody都不行
最后的解决方法:
@GetMapping("/t1")
public void down1(HttpServletResponse response) throws Exception {
response.reset();
response.setContentType("application/octet-stream;charset=utf-8");
response.setHeader(
"Content-disposition",
"attachment; filename=test.png");
try(
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\desktop\\1.png"));
// 输出流
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
){
byte[] buff = new byte[1024];
int len = 0;
while ((len = bis.read(buff)) > 0) {
bos.write(buff, 0, len);
}
}
}
参考资料和推荐阅读:
[1].https://www.jianshu.com/p/a93348d31d8d
[2].https://www.jianshu.com/p/da23cf7c1653
[3].http://www.wjhsh.net/lteal-p-5199911.html
[4].https://wenku.baidu.com/view/d1e44e4b1db91a37f111f18583d049649b660e9c.html?wkts=1669043878887&bdQuery=Springboot+getOutputStream%28%29+has+already+been+called+for+this+response
[5].https://blog.youkuaiyun.com/weixin_43296313/article/details/125100824