spring boot 用ResponseEntity实现下载文件(解决前后端分离跨域问题)
前言最近项目集成spring cloud了,所有接口都由网关转发,刚开始写了一个下载文件接口是直接将文件写到OutputStream的,但这样做后就会导致网关截拦器取不到用户信息(网关目前是单机部署,用户信息由security框架写到内存中的),最后用org.springframework.http.ResponseEntity实现了文件下载。1、OutputStream@ApiOpera...
前言
项目前后端分离,web端:vue,服务器:spring cloud。
最近项目集成spring cloud了,所有接口都由网关转发,刚开始写了一个下载文件接口是直接将文件写到OutputStream的,但这样做后就会导致网关截拦器取不到用户信息(网关目前是单机部署,用户信息由security框架写到内存中的),最后用org.springframework.http.ResponseEntity
实现了文件下载。
1、OutputStream方式
@ApiOperation(notes = "文件下载", value = "文件下载")
@RequestMapping("/download")
public void download(HttpServletResponse response,@RequestBody String id) {
//id 校验文件记录是否存在
FileObj fileobj = fileService.findByid(id);
//获取文件服务器路径
String fileId = fileobj.getid;
//从文件服务器下载文件到本地服务器,并返回路径
String downloadUrl = geturlfromServer(fileId);
if(StringUtils.isEmpty(downloadUrl)){
//return ;
}
log.info("下载文件名称:{}",fileobj.getfileName());
String fileName = null; // 文件名称的编码
InputStream in = null;
OutputStream out = null;
try {
response.reset();
fileName = new String(fileobj.getfileName().getBytes("Gb2312"), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName); // 设置文件头
File file = new File(downloadUrl + "/" +fileobj.getfileName());
in = new FileInputStream(file);
int len;
byte[] buffer = new byte[1024];
out = response.getOutputStream();
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if (null != out) {
out.close();
}
if(null != in){
in.close();
}
} catch (IOException var3) {
log.error(var3.getMessage(), var3);
}
}
}
这样是可以实现文件下载的,但由于框原因,用户信息取不到,又换了另一种方法
2、返回文件服务器url,由前端组件下载
上面方法丢失用户信息的原因,可能是由于清空了response的信息,导致框获取信息失败,我这里上传的文件是直接上传到文件服务器的,所以可以获取url地址直接在浏览器查看文件。
@ApiOperation(notes = "文件下载", value = "文件下载")
@GetMapping("/downloadurl")
public ResponseEntity<FileOutputOjb> download(HttpServletResponse response, @RequestParam("fileName") String fileName, @RequestParam("fileid") String fileid) {
//从文件服务器直接获取下载地址
//https://file.colck.com/sdfasdfasdf.pdf?token=sdfasdfasdf
String urlStr = geturlfromServer(fileid);
log.info("urlStr:{}",urlStr);
FileOutput fileOutput = new FileOutput();
fileOutput.setUrlStr(urlStr);
fileOutput.setFileName(fileName);
return ResponseEntity.ok(fileOutput);
}
返回Url,和原文件名(因为文件名传上服务器后会重命名成一串数字)。前端用组件可以实现下载,文件名也是原文件名。但必须要文件服务器配置允许跨域,否则就无法下载。即使申请了文件服务器同域名,虽然不再跨域但是还是无法下载(net::ERR_CONNECTION_RESET
)。最后用ResponseEntity实现
3、org.springframework.http.ResponseEntity
@ApiOperation(notes = "文件下载", value = "文件下载")
@GetMapping("/downloadfile")
public org.springframework.http.ResponseEntity<FileSystemResource> downloadFile(HttpServletResponse response,
@RequestParam("id") Long id, @RequestParam("fileId") String fileId) {
String downloadUrl = getfilePathfromServer(fileId);
log.info("下载文件名称:{}",fileId);
String fileName = null; // 文件名称的编码
InputStream in = null;
OutputStream out = null;
try {
fileName = new String(fileojb.getfileName.getBytes("Gb2312"), "ISO-8859-1");
//response.setHeader("Content-Disposition", "attachment;fileName=" + fileName); // 设置文件头
File file = new File(downloadUrl + "/" + fileojb.getfileName);
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Content-Disposition", "attachment; filename=" + fileName);
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.add("Last-Modified", new Date().toString());
headers.add("ETag", String.valueOf(System.currentTimeMillis()));
return org.springframework.http.ResponseEntity
.ok()
.headers(headers)
.contentLength(file.length())
.contentType(MediaType.parseMediaType("application/octet-stream"))
.body(new FileSystemResource(file));
} catch (Exception e) {
e.printStackTrace();
log.info("dfsId:{}下载文件失败,cause:{}",fielId,e);
}finally {
}
return org.springframework.http.ResponseEntity.status(Integer.parseInt(MsgCode.DEFINED_ERROR.getCode())).build();
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)