8

如何通过 spring 控制器提供大文件供下载?我关注了一些关于类似主题的讨论:

从弹簧控制器下载文件

但是对于 300mb - 600mb 的大文件,这些解决方案失败了。我在最后一行收到 OutOfMemoryException :

@RequestMapping(value = "/file/{dummyparam}.pdf", method = RequestMethod.GET, produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
public @ResponseBody byte[] getFile(@PathVariable("dummyparam") String dummyparam, HttpServletResponse response) {
.
.       
InputStream is = new FileInputStream(resultFile);

response.setHeader("Content-Disposition", "attachment; filename=\"dummyname " + dummyparam + ".pdf\"");
.
.         
return IOUtils.toByteArray(is);

我的(天真的)假设是 IOUtils 甚至可以处理大文件,但这显然不会发生。有什么方法可以在下载过程中将文件拆分成块?文件通常约为 300 - 600mb 大。最大并发下载数估计为 10。

简单的方法是将文件链接为 webserver 目录中的静态内容,但我们想尝试在我们的 Spring 应用程序中执行此操作。

4

2 回答 2

22

这是因为您正在将整个文件读入内存,请改用缓冲读写。

@RequestMapping(value = "/file/{dummyparam}.pdf", method = RequestMethod.GET, produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void getFile(@PathVariable("dummyparam") String dummyparam, HttpServletResponse response) {


    InputStream is = new FileInputStream(resultFile);

    response.setHeader("Content-Disposition", "attachment; filename=\"dummyname " + dummyparam + ".pdf\"");


    int read=0;
    byte[] bytes = new byte[BYTES_DOWNLOAD];
    OutputStream os = response.getOutputStream();

    while((read = is.read(bytes))!= -1){
        os.write(bytes, 0, read);
    }
    os.flush();
    os.close(); 
}
于 2013-04-04T00:33:28.710 回答
1

对于 Spring,需要在 ResponseEntity 中使用InputStreamResource类。

演示代码:

        MediaType mediaType = MediaTypeUtils.getMediaTypeForFileName(this.servletContext, fileName);
        System.out.println("fileName: " + fileName);
        System.out.println("mediaType: " + mediaType);

        File file = new File(DIRECTORY + "/" + fileName);
        InputStreamResource resource = new InputStreamResource(new FileInputStream(file));

        return ResponseEntity.ok()
                // Content-Disposition
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
                // Content-Type
                .contentType(mediaType)
                // Contet-Length
                .contentLength(file.length()) //
                .body(resource);
    }

参考链接:https ://o7planning.org/en/11765/spring-boot-file-download-example

于 2019-06-22T12:39:18.810 回答