I am trying to stream data from a JCR (Jackrabbit) workspace. The data I want to stream is a bunch of file chunks stored in jcr nodes (main node - file, subnodes - chunks). The chunks are base64 encoded strings.
I am using Magnolia CMS, that's using jackrabbit under the hood, it's also using JAX-RS.
The issue I am faced with is my heap running out of memory. This issue does not occur with files of smaller sizes (50MB-400MB, atleast these ones I have tested out and there are no issues with them AFAIK), however the moment I try out a file of around 1.2GB I run out of memory. Can somebody point me to the right direction of solving this issue?
@POST
@Path("/getFile/{fileId}")
@Produces({MediaType.APPLICATION_OCTET_STREAM})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 401, message = "ANONYMOUS TRIED TO ACCESS ENDPOINT")
})
public Response getFile(@PathParam("fileId") String fileId) {
AssetsManager assetsManager = new AssetsManager();
try {
Node asset = assetsManager.getAssetById(fileId);
Node assetData = asset.getNode("dataNodes");
int sliceCount = asset.getProperty("lastSlice").getDecimal().intValue();
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream output) throws IOException {
try {
for (int i = 0; i <= sliceCount; i++) {
Node sliceNode = assetData.getNode(String.valueOf(i));
byte[] decodedBytes = Base64.decodeBase64(sliceNode.getProperty("data").getString());
output.write(decodedBytes);
output.flush();
}
} catch (RepositoryException ex) {
// Handle RepositoryException appropriately
} finally {
output.close();
}
}
};
return Response.status(200).entity(stream)
.header("Content-Disposition", String.format("attachment; filename=%s",
asset.getProperty("name").getString()))
.header("Content-type", "application/octet-stream")
.header("Access-Control-Expose-Headers", "Content-Disposition")
.type(MediaType.APPLICATION_OCTET_STREAM)
.build();
} catch (Exception ex) {
return Response.status(400).entity(ex).build();
}
return Response.status(500).entity(ex).build();
}