Prevent Javascript adding metadata on File Upload to S3

Viewed 334

Basically I am willing to upload files directly to S3 via browser i.e without any web server acting as a middle-ware or proxy like this.

enter image description here

So I am generating pre-signed URL using boto3 library like this:

def put_url(self, key):
    url = self.client.generate_presigned_url(
        ClientMethod="put_object",
        Params={
            "Bucket": "visweswaran",
            "Key": key
        }
    )
    return url

and this returns a pre-signed URL which is completely fine. I am using JQuery to make ajax PUT request to the S3 to upload my file.

                let file_data = document.getElementById("file_data").files[0];
                var form = new FormData();
                form.append("", file_data, "test.txt");
                var settings = {
                  "url": url,
                  "method": "PUT",
                  "timeout": 0,
                  "processData": false,
                  "mimeType": "multipart/form-data",
                  "contentType": "text/plain",
                  "beforeSend": function(xhr){xhr.setRequestHeader('Content-Disposition', 'attachment');},
                  "data": form
                };
                $.ajax(settings).done(function (response) {
                  location.reload();
                });

The file gets uploaded to the S3 successfully via browser. But when I open the file I see strange meta data getting added to the top of the file like this,

-----------------------------33057860671031084693134041830 Content-Disposition: form-data; name="name"

test.txt -----------------------------33057860671031084693134041830 Content-Disposition: form-data; name="file"; filename="test.txt" Content-Type: text/plain

I have also tried a more formal solution like Pluploader (https://www.plupload.com/) and I am facing the same problem. I would like somebody to point me in the right direction to fix it. Ant help is much appreciated.

References:

  1. https://softwareontheroad.com/aws-s3-secure-direct-upload/
  2. How to upload to AWS S3 directly from browser using a pre-signed URL instead of credentials?

Working Solution

I have tested with a video and you don't need a form. Just send the data directly

let video = document.getElementById("video_file").files[0];
var settings = {
    "url": url,
    "method": "PUT",
    "timeout": 0,
    "processData": false,
    "data": video
};
$.ajax(settings).done(function (response) {
    location.reload();
});
1 Answers

I have tried uploading a txt file with a presigned-put-url using two approaches:

  1. Sending A form data: (this is used with POST urls not PUT)
  • This actually add the content-disposition header to the final file as mentioned in the question.
  1. Sending raw binary data (recommended way and this how PUT url is used!):
  • The file was uploaded correctly, and does not include the content-disposition header.

Could you try sending the PUT request without using formData at all?

The ajax's data attribute should have a value of file_data, and the content-type while the signing the S3 URL and sending (ajax) should be ContentType: 'binary/octet-stream'.

If you need to use formData, check out S3's preSignedPost.

Related