java下载接口
@PostMapping(value = "/download")
public void download(@RequestBody DownloadReq req, HttpServletRequest request, HttpServletResponse response) {
// 省略..........
String path = new File(path).getAbsolutePath() + File.separator + req.getFileName();
File file = new File(path);
if (!file.exists()) {
LOGGER.info("file:{}", file.getAbsolutePath());
LOGGER.info("下载文件不存在");
}
response.reset();
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setContentLength((int) file.length());
String fileInfoHear = String.format("attachment;filename=%s", req.getFileName());
response.addHeader("Content-Disposition", fileInfoHear);
String origin = request.getHeader("Origin");
response.addHeader("Access-Control-Allow-Origin", origin);
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Allow-Credentials", "true");
// 让浏览器能访问到其它响应头
response.addHeader("Access-Control-Expose-Headers","Content-Disposition");
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
byte[] buff = new byte[1024];
OutputStream os = response.getOutputStream();
int i = 0;
while ((i = bis.read(buff)) != -1) {
os.write(buff, 0, i);
os.flush();
}
LOGGER.info("file:{}, 下载成功", file.getAbsolutePath());
} catch (IOException e) {
LOGGER.error("异常", e);
}
// 只能返回null 或者方法是void, 否则会导致下载流关闭
}
java调用下载接口
public void download(DownloadReq req, String targetPath) {
Map<String, Object> params = new HashMap<>();
params.put("id", req.getId());
Path targetPathO = Paths.get(targetPath);
//定义请求头的接收类型
RequestCallback requestCallback = request -> {
request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
// json参数
request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
request.getBody().write(JSON.toJSONString(params).getBytes());
};
ResponseExtractor<Void> responseExtractor = response -> {
//对响应进行流式处理而不是将其全部加载到内存中
Files.copy(response.getBody(), targetPathO, StandardCopyOption.REPLACE_EXISTING);
return null;
};
// 省略代码.....
restTemplate.execute(url, HttpMethod.POST, requestCallback, responseExtractor);
log.info("下载文件:{}, 完成", req.getFileName());
}
前端调用下载接口
this.loading = true
axios({
method: 'post',
url: process.env.VUE_APP_BASE_API + '/download',
data: {
// json参数
id: this.$data.id
},
responseType: 'blob',
onDownloadProgress: (evt) => {
// 对原生进度事件的处理, 会在浏览器下方弹出下载文件框
this.setState({ progress: parseInt((evt.loaded / evt.total) * 100) });
}
}).then(response => {
let contentDisposition = response.headers['content-disposition']; //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
let filename = contentDisposition.split("filename=")[1];
// 将二进制流转为blob
let data = response.data ;
const blob = new Blob([data], { type: 'application/octet-stream' })
if (window.navigator.msSaveBlobOrOpenBlob) {
// 兼容IE,window.navigator.msSaveBlob:以本地方式保存文件
window.navigator.msSaveBlob(blob, decodeURI(filename))
} else {
// 创建新的URL并指向File对象或者Blob对象的地址
const blobURL = window.URL.createObjectURL(blob)
// 创建a标签,用于跳转至下载链接
const tempLink = document.createElement('a')
tempLink.style.display = 'none'
tempLink.href = blobURL
tempLink.setAttribute('download', decodeURI(filename))
// 兼容:某些浏览器不支持HTML5的download属性
if (typeof tempLink.download === 'undefined') {
tempLink.setAttribute('target', '_blank')
}
// 挂载a标签
document.body.appendChild(tempLink)
tempLink.click()
document.body.removeChild(tempLink)
// 释放blob URL地址
window.URL.revokeObjectURL(blobURL)
}
}).finally(() => {
this.loading = false
})