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;
    }
posted @ 2024-03-12 17:21  土豆泥呀  阅读(5023)  评论(0)    收藏  举报