dgarceran
dgarceran

Reputation: 187

Return image AWS S3 (S3Object) Spring REST controller

I'm trying to return images from my S3 bucket. Everything works perfect, my service uploads and gets images, but the problem is that when I try to return them through the REST Controller, the image doesn't appear on browser.

Here is where I fetch the image from S3:

public S3Object getImageFromS3Bucket(String fileName) {
    S3Object object = s3client.getObject(new GetObjectRequest(bucketName, fileName));
    return object;
}

public byte[] getByteArrayFromImageS3Bucket(String fileName) throws IOException {
    InputStream in = getImageFromS3Bucket(fileName).getObjectContent();
    byte[] byteArray = IOUtils.toByteArray(in);
    in.close();

    return byteArray;
}

and here is my controller:

@RequestMapping(value = "/getImage/{fileName}", method = RequestMethod.GET)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody
public ResponseEntity<byte[]> downloadImage(@PathVariable("fileName") String fileName) throws IOException {
    byte[] media = s3BucketTestService.getByteArrayFromFile(fileName);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.IMAGE_PNG);
    headers.setContentLength(media.length);

    return new ResponseEntity<>(media, headers, HttpStatus.OK);
}

Here are the response headers:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 10645
Content-Type: image/png
Date: Mon, 14 May 2018 09:41:47 GMT
Expires: 0
Pragma: no-cache
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block

I also have this bean in my configuration:

@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
    return arrayHttpMessageConverter;
}

private List<MediaType> getSupportedMediaTypes() {
    List<MediaType> list = new ArrayList<MediaType>();
    list.add(MediaType.IMAGE_JPEG);
    list.add(MediaType.IMAGE_PNG);
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    return list;
}

Anyone knows what am I doing wrong? The browser creates a png image with the exact size of the file I'm trying to get, so I guess the only problem is the visualization of the image?

PD: I don't want to make the image downloadable, I just want to generate that resource so the front-end can read it.

Upvotes: 2

Views: 5616

Answers (3)

Red Boy
Red Boy

Reputation: 5739

I answered to one of similar question, it was related to PDF. If you just change the MediaType to PNG/JPEG, it should work. Take a look at it.

Upvotes: 0

piy26
piy26

Reputation: 1612

Try Using ImageIO API to convert the raw bytes from S3 bucket to Image Bytes as below:

public byte[] getByteArrayFromImageS3Bucket(String fileName) throws IOException {
    InputStream in = getImageFromS3Bucket(fileName).getObjectContent();

    BufferedImage imageFromAWS = ImageIO.read(in);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(imageFromAWS, "png", baos );
    byte[] imageBytes = baos.toByteArray();
    in.close();
    return imageBytes;

}

Upvotes: 3

David
David

Reputation: 8206

Might be a silly question, but are you very sure that the MIME type of the image is in fact PNG? Perhaps the browser has been doing some MIME sniffing and is getting confused between what it finds as the advertised content-type vs what the file format appears to be? I see you have set X-Content-Type-Options: nosniff but I am just curious to ensure first that the file format is correct.

Upvotes: 0

Related Questions