Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading images to Spring Boot and S3 all In-Memory

I have an Angular webapp that uses a Spring Boot REST service as its backing web service.

I am adding a "Profiles" feature for users, and as part of this I want to stand up an endpoint that allows users to upload profile images for themselves and immediately upload those files to S3 (where I will host all the images from).

Looking at several Spring Boot/file upload tutorials :

  • http://www.mkyong.com/spring-boot/spring-boot-file-upload-example/
  • I update avatar image and display it but the avatar does not change in Spring Boot , why?
  • Many others

It seems that the standard way of handling such file upload is exposing a controller endpoint that accepts MultipartFiles like so:

@RestController
@RequestMapping("/v1/profiles")
public class ProfileController {
    @PostMapping("/photo")
    public ResponseEntity uploadProfilePhoto(@RequestParam("mpf") MultipartFile mpf)
        // ...
}

Looking at all this code, I can't tell if the MultipartFile instance is in-memory or if Spring sets its location somewhere (perhaps under /tmp?) on the disk.

Looking at the AWS S3 Java SDK tutorial, it seems the standard way to upload a disk-based File is like so:

File file = new File(uploadFileName);
s3client.putObject(new PutObjectRequest(bucketName, keyName, file));

So it looks like I must have a File on disk in order to upload to S3.

I'm wondering if there is a way to keep everything in memory, or whether this is a bad idea and I should stick to disks/File instances!

  • Is there a way to keep the entire profile image (MultipartFile) in-mempory inside the controller method?
  • Is there a way to feed (maybe via serialization?!) a MultipartFile instance to S3's PutObjectRequest?
  • Or is this all a terrible idea (if so, why?!)?
like image 634
smeeb Avatar asked Nov 07 '22 11:11

smeeb


1 Answers

Is there a way to keep the entire profile image (MultipartFile) in-mempory inside the controller method?

No, there is NO way to keep an image File in-memory because File object in java represents a path in file system.

Is there a way to feed (maybe via serialization?!) a MultipartFile instance to S3's PutObjectRequest?

No, from S3's API documentation, there is no way for S3 to deserialize to the image file for you after/during the upload.

Or is this all a terrible idea (if so, why?!)?

It depends on your specific case but it is generally not preferred.
If - there are not many users uploading images at the same time, your memory is probably enough to handle.
Else - You can easily get out-of-memory problems.

If you insist on doing so, S3 API can upload an InputStream (If I remember correctly). You can convert your Multipart File to an InputStream.
This SO thread talks about uploading to S3 with InputStream

You can also take a look at File.createTempFile() to create a temp file.

like image 114
Minjun Yu Avatar answered Nov 14 '22 23:11

Minjun Yu