7

We are trying to upload a file to S3 using jQuery ajax & a presigned url. We generate the presigned url on the server. Currently we are trying to use FormData to upload the file.

          var uploadData = new FormData(),
            files = $(this.input).prop('files'),
            file = files[0];

          uploadData.append('file', file);

          $.ajax({
            url: '{presigned url string}',
            type: 'PUT',
            data: uploadData,
            cache: false,
            processData: false,
            contentType: false,
            success: function(response) {
              console.log('S3 upload success!');
            },
            error: function(response) {
              console.log('Error with S3 upload: ' + response.statusText);
            }
          });

This returns a SignatureDoesNotMatch error from AWS:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we 
calculated does not match the signature you provided. Check your key and 
signing method.</Message><StringToSignBytes>50 55 54 0a 0a 6d 75 6c 74 69 70 61 72 74 2f 66 6f 72 6d 2d 64 61 74 61 3b 20 62 6f 75 6e 64 61 72 79 3d 2d 2d 2d 2d 57 65 62 4b 69 74 46 6f 72 6d 42 6f 75 6e 64 61 72 79 67 57 6f 4a 73 42 56 79 41 4c 57 71 51 6b 73 69 0a 31 34 30 39 37 37 37 32 39 33 0a 2f 64 69 2d 6b 79 72 73 74 65 6e 2d 64 65 61 6c 73 2f 76 4e 79 4b 4e 55 4c 37 51 68 4f 30 45 4b 38 52 58 44 70 32 59 77 25 32 46 63 35 37 65 64 37 62 39 2d 64 63 61 62 2d 34 63 30 62 2d 62 36 63 30 2d 36 31 66 30 36 62 32 30 37 34 66 31 2d 74 65 73 74 2e 74 78 74</StringToSignBytes>
<RequestId>ED7C581570F547DB</RequestId><HostId>ZT6LsFYCbo1L0gYNcUwtdCWF6SNnyuUyKiL60ntJEZugx3cnDN/yH5KBjgEiBv5c</HostId><SignatureProvided>N2d7oNMVHvI6yxAXujNy8O5cF24=</SignatureProvided>
<StringToSign>PUT

multipart/form-data; boundary=----WebKitFormBoundarygWoJsBVyALWqQksi
1409777293
/test-bucket/vNyKNUL7QhO0EK8RXDp2Yw%2Fc57ed7b9-dcab-4c0b-b6c0-61f06b2074f1-test.txt</StringToSign><AWSAccessKeyId>FAKEACCESSKEY</AWSAccessKeyId></Error>  

I know that the presigned url works because I can upload the file correctly via CURL:

curl -v --upload-file {filename} {presigned url}

1 Answer 1

7

We found the issue ourselves. Here is the code we were using to generate the pre-signed url:

val dt: DateTime = new DateTime()
val expiration = DateTime.now.plusMillis(timeout.toInt)
val presignedUrlRequest: GeneratePresignedUrlRequest =
  new GeneratePresignedUrlRequest(awsBucket, key, HttpMethod.PUT)
presignedUrlRequest.setExpiration(expiration.toDate())
// WE ADDED THIS LINE
presignedUrlRequest.setContentType("multipart/form-data")

s3client.generatePresignedUrl(presignedUrlRequest).toString()

We had to set the content type in the presignedUrlRequest as well as add
headers: {'Content-Type': 'multipart/form-data'} to our ajax call.

The way we were generating the url at first worked with CURL since we weren't setting the content-type in the presignedUrlRequest and curl wasn't setting a content-type.

Sign up to request clarification or add additional context in comments.

2 Comments

I am getting the same problem, but setting content type hasn't helped. Would love some assistance!
This solution worked great for me, but the file that was uploaded to S3 had the FormData values appended to it. Do you know how to prevent this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.