Close CloseableHttpResponse after returning InputStream Spring MVC

481 views Asked by At

My controller method returns InputStreamResource in response body. I'am getting InputStream from the CloseableHttpResponse in the TRY block and I close CloseableHttpResponse in FINALLY block.

The problem is that finally is called before the return and there is no chance to create InputStreamResource from the InputStream because CloseableHttpResponse is already closed.

What could be a possible solution in this case? Can I somehow close CloseableHttpResponse after returning InputStreamResource? I really need to use CloseableHttpClient and the method should return some stream.

    public ResponseEntity<InputStreamResource> getFileAsStream(@PathVariable("uuid") String uuid) throws IOException, InterruptedException {
        CloseableHttpResponse response = fileService.importFileByUuid(uuid);
        try {
            HttpEntity entity = response.getEntity();
            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(entity.getContentLength()));
            responseHeaders.add(HttpHeaders.CONTENT_TYPE, entity.getContentType().getValue());
            responseHeaders.add(HttpHeaders.CONTENT_DISPOSITION, response.getFirstHeader(HttpHeaders.CONTENT_DISPOSITION).getValue());

            if (entity != null) {
                InputStream inputStream = entity.getContent();
                InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
                return ResponseEntity.ok()
                            .headers(responseHeaders)
                            .body(inputStreamResource);
            }
            throw new IllegalStateException(String.format(
                    "Error during stream downloading, uuid = %s", uuid));
        } finally {
            response.close();
        }
    } 
1

There are 1 answers

2
Karim On

You can always create a copy of the InputStream obtained from the HttpEntity and use the copy to create the InputStreamResource that is returned in the ResponseEntity. This way, the original InputStream obtained from the HttpEntity can be safely closed before the ResponseEntity is returned.

InputStream inputStream = entity.getContent();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
IOUtils.copy(inputStream, outputStream);
byte[] contentBytes = outputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(contentBytes);
InputStreamResource inputStreamResource = new InputStreamResource(byteArrayInputStream);

Or save use the byte[] and use it to return ByteArrayResource instead of InputStreamResource