Devo rettificare un'applicazione che fondamentalmente serve contenuti utilizzando due endpoint REST. Entrambi gli endpoint trasferiscono i file al browser, un endpoint lo fa fornendo il file in formato binario, l'altro invia il file base64 codificato.
L'applicazione aveva una perdita di handle di file nell'endpoint che serve dati binari. Il motivo è che è stato utilizzato un InputStream
che non potrebbe mai essere chiuso perché non potevo farlo prima di consegnarlo a Spring e Spring non l'ha chiuso.
Il codice per la funzione 1 ora assomiglia a questo e funziona bene nel senso che non crea una perdita e trasmette il contenuto di file anche enormi senza consumare molta memoria:
public ResponseEntity<?> getContentAsBinary(@RequestParam(value = "id", defaultValue = "") id ) {
/// stuff not relevant here
FileSystemResource fsr = new FileSystemResource(fileName);
return ResponseEntity.status(HttpServletResponse.SC_OK).body(fsr);
}
La funzione problematica voglio migliorare aspetto come questo:
public ResponseEntity<byte[]> getContentAsBase64(@RequestParam(value = "id", defaultValue = "") id ) {
/// stuff not relevant here
byte[] bytes = IOUtils.toByteArray(content);
try {
content.close();
} catch (Exception e) {
log.warn("Error closing inputstream of id {}", id);
}
return ResponseEntity.status(HttpServletResponse.SC_OK).body(Base64.encodeBase64(bytes));
}
Ha il grande svantaggio di copiare il file completo in memoria prima di convertirlo in base64. Preferirei un approccio in cui il contenuto viene trasmesso in streaming e codificato Base64 durante lo streaming.