Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use InputStreamResource to return an image as ByteArray into a Spring application?

I am working on a Spring Boot backend application.

I have to retrieve a jpg image from a BLOB field on my database and return it to the frontend.

Searching online I have found this tutorial about how the controller should return a file to display: http://www.leveluplunch.com/java/tutorials/032-return-file-from-spring-rest-webservice/

As you can see in the previous tutorial it do something like this:

@RequestMapping(value = "/", method = RequestMethod.GET, produces = "application/pdf")
public ResponseEntity<InputStreamResource> downloadPDFFile()
        throws IOException {

    ClassPathResource pdfFile = new ClassPathResource("pdf-sample.pdf");

    return ResponseEntity
            .ok()
            .contentLength(pdfFile.contentLength())
            .contentType(
                    MediaType.parseMediaType("application/octet-stream"))
            .body(new InputStreamResource(pdfFile.getInputStream()));
}

So, it is returning a InputStreamResource object wrapped into a ResponseEntity.

In the past I do it using a standard Java array of bytes. Reading the documentation I found that InputStreamResource is a specific Spring object: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/InputStreamResource.html

So, from what I have understand, I have the standard Java InputStream type that is an abstract class that is is the superclass of all classes representing an input stream of bytes (so something like as I done in the past). Then the InputStreamResource (used in the previous tutorial) is a specific Resource implementation of the InputStream.

Reading the documentation Resource is a Spring interface used to describe any type of resources (so images, files, etcetc).

So my doubt is this InputStreamResource the right choice to return a JPEG files to my front-end application as byte array?

I have this doubt because in the official documentation I read:

Should only be used if no other specific Resource implementation is applicable. In particular, prefer ByteArrayResource or any of the file-based Resource implementations where possible.

Is it a good solution?

like image 711
AndreaNobili Avatar asked Nov 13 '16 15:11

AndreaNobili


1 Answers

In general it is a good idea to stream your results back to the client. The simple reason for that is that images and attachments are getting larger. When you return a byte array, you have to have all of those bytes in memory at once. That introduces you to an accidental denial of service incident if your image or attachment you are sending is too large to be in memory at once.

General Guidelines:

  • If there is a better resource type, use that. In your case you can just return your ClassPathResource in your response entity.
  • There's also a FileSystemResource to return a file on disk
  • Use InputStreamResource if there isn't already another resource type. Example is returning blob content

Example of how to use the InputStreamResource:

    return new InputStreamResource(blob.getPayload().openStream()) {
        @Override
        public long contentLength() {
            return blob.getMetadata().getContentMetadata().getContentLength();
        }
    };

I would caution against the lazy thinking of returning a byte array. It should only be considered if your response sizes are about 1MB or less.

like image 130
Berin Loritsch Avatar answered Oct 21 '22 14:10

Berin Loritsch