Closed
Description
Environment: SpringBoot 2.7.10, SpringWeb 5.3.26, Java 11
There is a file download api which uses Amazon S3, and the return result is a ResponseEntity
@GetMapping("/download/{id}")
public ResponseEntity<Resource> download(@PathVariable("id") String id) {
S3Object s3Object = amazonS3.getObject(bucket, id);
ObjectMetadata metadata = s3Object.getObjectMetadata();
Resource resource = new InputStreamResource(s3Object.getObjectContent());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, metadata.getContentType())
.header(HttpHeaders.CONTENT_LENGTH, String.valueOf(metadata.getContentLength()))
.body(resource);
}
It works fine until invalid content types appear, such as "excel". The InputStream of the S3Object is not closed because SpringWeb failed to parse the content type. It leads to memory leaks and connection pool leaks.
I can not do anything in this situation because I am not sure if the return will result in any exceptions. So I have to use try-with-resources instead:
@GetMapping("/download/{id}")
public void download(@PathVariable("id") String id, HttpServletResponse response) throws IOException {
S3Object s3Object = amazonS3.getObject(bucket, id);
try (InputStream inputStream = s3Object.getObjectContent()) {
ObjectMetadata metadata = s3Object.getObjectMetadata();
response.setHeader(HttpHeaders.CONTENT_TYPE, metadata.getContentType());
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(metadata.getContentLength()));
inputStream.transferTo(response.getOutputStream());
}
}
In my opinion, the Spring framework should be responsible for closing the input stream that I return, no mater what exception occurs.
If my viewpoint is incorrect, please tell me the standard implementation for file downloads.
Thanks