feign下载文件

/ 技术收藏 / 没有评论 / 419浏览

服务提供者

@ApiOperation("下载文件")
@GetMapping("/download")
public void download(HttpServletRequest request, HttpServletResponse response, @RequestParam("path")String path) throws IOException {
	request.setCharacterEncoding("utf-8");
	File file = new File(path);
	String fileName = file.getName();
	ServletOutputStream outputStream = response.getOutputStream();
	response.setContentType("application/octet-stream");
	fileName = new String(fileName.getBytes("UTF-8"),"ISO8859-1");
	response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
	byte[] buffer = new byte[1024];
	int readLength;
	FileInputStream fis = new FileInputStream(file);
	while ((readLength=fis.read(buffer))!= -1) {
		outputStream.write(buffer, 0, readLength);
		outputStream.flush();
	}
	IoUtil.close(fis);
	IoUtil.close(outputStream);
}

服务消费者

feign接口,必须返回Response

@GetMapping("/download")
Response downloadFile( @RequestParam("path")String path) throws IOException;

controller

@ApiOperation(value = "下载文件")
@GetMapping("/downloadFile")
public void downloadFile(HttpServletResponse response, @RequestParam("path")String path) throws IOException {
	Response responseFromRemote = proxyFileFeign.downloadFile(path);
	HttpUtil.downloadFeignFile(response, responseFromRemote);
}

工具类实现

/**
 * feign代理下载文件工具
 * @param responseFromRemote feign的response
 * @date 2022/4/22
 */
public static void downloadFeignFile(HttpServletResponse response, Response responseFromRemote) throws IOException {
	Response.Body body = responseFromRemote.body();
	/**FilterInputStream**/
	InputStream inputStream = body.asInputStream();
	OutputStream  outputStream = response.getOutputStream();
	response.setHeader("content-disposition",responseFromRemote.headers().get("content-disposition").stream().collect(Collectors.joining(";")));
	response.setHeader("content-type",responseFromRemote.headers().get("content-disposition").stream().collect(Collectors.joining(";")));
	byte[] buffer = new byte[1024 * 8];
	int count;
	while ((count = inputStream.read(buffer)) != -1) {
		outputStream.write(buffer, 0, count);
		outputStream.flush();
	}
	IoUtil.close(inputStream);
	IoUtil.close(outputStream);
}

读写文件需要注意的点

1.文件大小未知的情况,不要一次性读取整个文件进内存,太耗内存,甚至oom

2.小文件如果一次性读取,inputStream.available()的返回值不是全部字节大小,根据jdk注释

Returns:
an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking or 0 when it reaches the end of the input stream.

返回的是预估可以一次性不阻塞读取的大小。