Skip to content

Downloading big files can run out of memory #6720

Description

@juanluisrp

With large attachments having the content of the files as a byte array in memory can cause problems running out of memory.

public HttpEntity<byte[]> getResource(
@Parameter(description = "The metadata UUID", required = true, example = "43d7c186-2187-4bcd-8843-41e575a5ef56") @PathVariable String metadataUuid,
@Parameter(description = "The resource identifier (ie. filename)", required = true) @PathVariable String resourceId,
@Parameter(description = "Use approved version or not", example = "true") @RequestParam(required = false, defaultValue = "true") Boolean approved,
@Parameter(description = "Size (only applies to images). From 1px to 2048px.", example = "200") @RequestParam(required = false) Integer size,
@Parameter(hidden = true) HttpServletRequest request) throws Exception {
ServiceContext context = ApiUtils.createServiceContext(request);
try (Store.ResourceHolder file = store.getResource(context, metadataUuid, resourceId, approved)) {
ApiUtils.canViewRecord(metadataUuid, request);
MultiValueMap<String, String> headers = new HttpHeaders();
headers.add("Content-Disposition", "inline; filename=\"" + file.getMetadata().getFilename() + "\"");
headers.add("Cache-Control", "no-cache");
String contentType = getFileContentType(file.getPath());
headers.add("Content-Type", contentType);
if (contentType.startsWith("image/") && size != null) {
if (size >= MIN_IMAGE_SIZE && size <= MAX_IMAGE_SIZE) {
BufferedImage image = ImageIO.read(file.getPath().toFile());
BufferedImage resized = ImageUtil.resize(image, size);
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(resized, "png", output);
output.flush();
byte[] imagesB = output.toByteArray();
output.close();
return new HttpEntity<>(imagesB, headers);
} else {
throw new IllegalArgumentException(String.format(
"Image can only be resized from %d to %d. You requested %d.",
MIN_IMAGE_SIZE, MAX_IMAGE_SIZE, size));
}
} else {
return new HttpEntity<>(Files.readAllBytes(file.getPath()), headers);
}

This should be written to the servlet output stream directly instead of loading the file in memory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions