SpringBoot文件下载
SpringBoot文件下载
文件下载方式的选择需要根据结合实际情况选择,如果是下载小文件,则可以读取整个文件先放入内存中,如果文件有几十上百兆,则应该考虑使用缓冲流,避免读取内容过大导致内存资源耗尽乃至宕机。
指定下载文件名称
下载文件时使用指定文件名称进行保存文件,需要在响应头中设置属性Content-Disposition中的filename,示例如下:
response.setHeader("Content-Disposition", "attachment; filename=\"test.jpg\");
其中Content-Disposition的参数中可以指定响应数据以attachment方式保存到本地,或以 inline在线预览方式返回, inline方式时ContentType需明确具体类型,如image/jpeg、application/pdf。
-
响应头的参数顺序需要在输出流前面设置,否则文件名不生效;
-
如果文件名称是中文,在保存时把文件名的编码格式转换成
ISO-8859-1,否则文件名可能是下划线。
// 文件名UTF-8格式转成ISO_8859_1
String filenameResult = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
1.下载小文件
方式一
使用工具类方法将文件直接转成字节数组,而后放入response响应流中。
@GetMapping("/download")
public void downloadFile(HttpServletResponse response) throws IOException {
// 指定要下载的文件路径
String filePath = "/home/6E800B0652F1649C0E49BB7CF108AB39.jpg";
File file = new File(filePath);
// 设置响应头信息
String filename = file.getName();
// 文件转成字节数组
byte[] fileByte = Files.readAllBytes(file.toPath());
// 设置response的Header
response.setCharacterEncoding("UTF-8");
// 指定下载文件名(attachment-以下载方式保存到本地,inline-在线预览)
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
// 告知浏览器文件的大小
response.addHeader("Content-Length", "" + file.length());
// 内容类型为通用类型,表示二进制数据流
response.setContentType("application/octet-stream");
OutputStream os = response.getOutputStream();
os.write(fileByte);
os.flush();
}
方式二
使用ResponseEntity返回字节数组,支持小文件下载。
@GetMapping("/download2")
public ResponseEntity<byte[]> downloadFile2() throws IOException {
// 指定要下载的文件路径
String filePath = "/home/6E800B0652F1649C0E49BB7CF108AB39.jpg";
File file = new File(filePath);
// 设置响应头信息
String filename = file.getName();
// 文件转成字节数组
byte[] fileByte = Files.readAllBytes(file.toPath());
HttpHeaders headers = new HttpHeaders();
// 指定下载文件名(attachment-以下载方式保存到本地,inline-在线预览)
// headers.add("Content-Disposition", "inline; filename=\"" + filename + "\"");
headers.setContentDisposition(ContentDisposition.builder("inline").filename(filename, StandardCharsets.ISO_8859_1).build());
headers.setContentType(MediaType.parseMediaType("application/octet-stream"));
headers.setContentLength(file.length());
// 构建响应实体(可以返回<byte[]或Resource,返回类型取决body入参类型)
ResponseEntity<byte[]> responseEntity = ResponseEntity.ok().headers(headers).body(fileByte);
return responseEntity;
}
2.大文件下载
方式一
将文件转成输入流,通过循环边读边写方式写入到response输出流中。
@GetMapping("/download3")
public void downloadFile3(HttpServletResponse response) throws IOException {
// 指定要下载的文件路径
String filePath = "/home/test.zip";
File file = new File(filePath);
// 设置响应头信息
String filename = file.getName();
// 设置response的Header
response.setCharacterEncoding("UTF-8");
// 指定下载文件名(attachment-以下载方式保存到本地,inline-在线预览)
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
// 告知浏览器文件的大小
response.addHeader("Content-Length", "" + file.length());
// 内容类型为通用类型,表示二进制数据流
response.setContentType("application/octet-stream");
try(InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())){
byte[] buff = new byte[2048];
int len;
while ((len = bis.read(buff)) != -1){
bos.write(buff, 0, len);
}
bos.flush();
} catch (IOException e){
throw e;
}
}
try里面的代码可以使用工具类FileCopyUtils.copy(bis, bos);替换。
方式二
使用ResponseEntity返回Resource,支持大文件下载
@GetMapping("/download5")
public ResponseEntity<Resource> downloadFile5() throws IOException {
// 指定要下载的文件路径
String filePath = "/home/6E800B0652F1649C0E49BB7CF108AB39.jpg";
File file = new File(filePath);
// 设置响应头信息
String filename = file.getName();
// 创建资源对象(以绝对路径访问系统资源)
Resource resource = new FileSystemResource(file);
HttpHeaders headers = new HttpHeaders();
// 指定下载文件名(attachment-以下载方式保存到本地,inline-在线预览)
// headers.add("Content-Disposition", "inline; filename=\"" + filename + "\"");
headers.setContentDisposition(ContentDisposition.builder("inline").filename(filename, StandardCharsets.ISO_8859_1).build());
headers.setContentType(MediaType.parseMediaType("application/octet-stream"));
headers.setContentLength(file.length());
// 构建响应实体(可以返回<byte[]或Resource,返回类型取决body入参类型)
ResponseEntity<Resource> responseEntity = ResponseEntity.ok().headers(headers).body(resource);
return responseEntity;
}

浙公网安备 33010602011771号