前言
有时候项目里需要下载文件的功能,但是一时之间不知道从何下手,故此记录。
一、使用HttpServletResponse
最简单方便的便是使用HttpServletResponse,设置一下请求头,获取到输出流。
public static void download(HttpServletRequest request, HttpServletResponse response)throws Exception {
String fileName = "要下载的文件的名字";
String filePath = "要下载的文件在服务器的存储地址";
//设置响应头和客户端保存文件名
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
//打开本地文件流
InputStream in = new FileInputStream(filePath);
//激活下载操作
OutputStream os = response.getOutputStream();
try {
//循环写入输出流
byte[] b = new byte[2048];
int length;
while ((length = in.read(b)) > 0) {
os.write(b, 0, length);
}
} catch (Exception e){
throw e;
} finally {
os.close();
in.close();
}
}
但是有时候前端拿不到文件名称,就需要把文件名称用URLEncoder编码一下。输出流和输出流的转换可以使用Hutool工具类,这样编码会更加简单。
@GetMapping("/doc")
public void downloadStatisticsDoc(HttpServletResponse response) throws Exception {
//response设置
String today = DateUtil.today();
String fileName = "txt文件名称" + today + ".txt";
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()));
//文档内容
String statistics = "要下载的文本内容";
try(BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(statistics.getBytes()));
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream())
){
IoUtil.copy(in, out);
}
}
二、使用ResponseEntity
使用方法基本一样,就是稍微简介了一些,也可以下载byte数组。
public ResponseEntity<Object> download(HttpServletRequest request)throws Exception{
byte[] data = "获取到的byte数组,也可以是输入流读取来的";
String fileName = "文件名字";
//设置响应头
HttpHeaders headers = new HttpHeaders();
headers.setCacheControl("no-cache, no-store, must-revalidate");
//防止中文乱码
headers.setContentDispositionFormData("attachment",new String(fileName.getBytes("UTF-8"), "iso-8859-1"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
//headers.setContentLength(file.getContentLength());
headers.setPragma("no-cache");
return new ResponseEntity<Object>(data, headers, HttpStatus.CREATED);
}
写在最后的话
这两种下载方式各有优缺点吧,ResponseEntity比较简洁一些,但是是一种一次性读取的下载方式,下载太大文件会导致内存溢出。使用response对下载的文件大小无限制(循环读取一定量的字节写入到输出流中,因此不会造成内存溢出,但是在下载人数过多的时候应该还是出现一些异常)。