Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading files through a play framework app to S3 without "touching" the disk

I have to implement a server that lets some users upload possibly huge files (multi gigabytes worth of files) to S3 (they do not know it is S3 though). I have already implemented something similar in Python and a basic implementation using Play framework.

Right now my uploading function looks like this:

public Result uploadFile() {
      List<Http.MultipartFormData.FilePart> files = request().body().asMultipartFormData().getFiles();
      if (CollectionUtils.isNotEmpty(files)) {
          Bucket bucket = MY_BUCKET;
          UUID timeuuid;
          Promise<UploadResult> promise;
          ObjectNode responseMessage = Json.newObject();  
          for (Http.MultipartFormData.FilePart file : files) {
              timeuuid = TimeUUID.now();
              promise = Promise.promise(new UploadFunction(timeuuid, bucket, file.getFile(), obtainS3Connection()));
              responseMessage.set(file.getFilename(), TextNode.valueOf(timeuuid.toString()));
          }
          return accepted(responseMessage);
      } else {
          return badRequest("files empty");
      }
}

I am not worried about the upload code itself and actually I already have implemented it many times. What I am worried about is making it so that Play! does not save Files to disk and that the files sent only "pass through" my server without being written to disk (even as temp files). I have some processing involved and sometime "Client side" encryption of some content by I can do that as a Stream.

I was wondering if Play already does that? Or how would I achieve that?

What I am assuming Play (and Django in my previous version of this service) does is:

Upload --> Play       MyProcessing -------> S3
               \     /
                \   /
                 Disk

What I would like it to do :

Upload --> Play --> MyProcessing -------> S3

The reason I want to do this is that I want the potential to deploy my service on instances with very small disks and I also want the guarantee that nobody can find the unencrypted file (if I choose to encrypt it) once uploaded.

UPDATE: I am not giving up ... just yet.

I have found a few possible solution that unfortunately use Scala. They all revolve around the same theme as this discussion: Play 2.x : Reactive file upload with Iteratees

I was wondering if this would be possible using Java (I am the only one in my company that knows Scala so I cannot roll out something for which I would be the only person able to do maintenance on it ... because sometimes I wish to take breaks or go on other projects).

like image 316
le-doude Avatar asked Mar 18 '14 05:03

le-doude


People also ask

How do I push files to AWS S3?

To upload folders and files to an S3 bucketSign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/ . In the Buckets list, choose the name of the bucket that you want to upload your folders or files to. Choose Upload.

Does S3 replace files with same name?

As @VsevolodGoloviznin says, uploading a file with the same path and name (S3 calls this the object key) should automatically replace the old file with the new. The old file will not actally be deleted but will instead only be hidden if versioning is enabled on the bucket.


1 Answers

I have never done this with Play however I have done something similar in Java. The route to success for us was to directly post files to S3. Basically what you do is you generate an upload form for the user where the post URL is not provided by your service but by Amazon and the users browser is directly uploading to S3.

On upload success S3 will then return an empty document with status code 200 when the object is successfully uploaded. In our case we perform the post call via jQuery and wait for the jQuery success handler on the post and only after that we update our systems database. Alternatively it is possible to specify a redirect form field with an URL where the user gets redirected to after successful upload.

Details on this can be found here: http://doc.s3.amazonaws.com/proposals/post.html

like image 181
Matthias Steinbauer Avatar answered Nov 03 '22 12:11

Matthias Steinbauer