smeeb
smeeb

Reputation: 29477

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 :

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!

Upvotes: 5

Views: 3798

Answers (2)

Lance
Lance

Reputation: 123

I have been looking at the same thing. Basically you want a user to be able to be able to upload a photo album and have those photos served from S3 and probably have them secured so only that user can upload/delete/etc.

I believe the simpler answer is in spring boot to get a Pre-signed URL from S3. https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObjectJavaSDK.html

which basically gives you a token defining the bucket, and object key ("/bobs_profile/smiling_bob.jpg") and a time limit for that image to be uploaded.

Give that to your angular app (or ionic app) to upload the image to that location.

That should do it. but someone let me know if I'm wrong.

The only issue that I see is if bob wants to upload "bobs_nude_photo.jpg" and only wants spring security logged in people to be able to see it... well I'm sure there is an S3 solution for that??

Upvotes: 1

Alex Minjun Yu
Alex Minjun Yu

Reputation: 3707

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.

Upvotes: 1

Related Questions