I'm trying to upload files to S3 via Cloudfront. I've created a bucket with name my-files. Bucket CORS settings:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
I've created Cloudfront distribution. Here is configuration which can be important:
General:
Delivery Method: Web
Alternate Domain Names (CNAMEs) files.example.com
Origins:
Origin Domain Name: my-files.s3.amazonaws.com
Restrict Bucket Access: Yes
Grant Read Permissions on Bucket: Yes, Update Bucket Policy
Behaviour:
Path Pattern: Default (*)
Origin: S3-my-files
Viewer Protocol Policy: HTTP and HTTPS
Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Whitelist Headers: Access-Control-Request-Headers, Access-Control-Request-Method, Origin
Object Caching: Use Origin Cache Headers
Restrict Viewer Access (Use Signed URLs or Signed Cookies): Yes
Trusted Signers: Self
I can create signed URL for file download and it works correctly. I can create CNAME for S3 bucket, upload a file to S3 using pre-signed URL and this also works correctly. When I'm trying to upload file via Cloudfront then I'm getting a 403 response (OPTIONS):
XMLHttpRequest cannot load http://files.example.com/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://0.0.0.0:5000' is therefore not allowed access. The response had HTTP status code 403.
Is it possible to use Cloudfront with signed URLs for uploading files? How can I set allowed origins to allow file uploads from localhost?
Aws recommend to use CloudFront for upload/download file < 1Gb in size. For larger files, the S3 Transfer Accelerator is recommended.
In the Amazon S3 console, choose the bucket where you want to upload an object, choose Upload, and then choose Add Files. In the file selection dialog box, find the file that you want to upload, choose it, choose Open, and then choose Start Upload. You can watch the progress of the upload in the Transfer pane.
Storing your static content with S3 provides a lot of advantages. But to help optimize your application's performance and security while effectively managing cost, we recommend that you also set up Amazon CloudFront to work with your S3 bucket to serve and protect the content.
Delivering from Amazon CloudFront Now we start seeing a small improvement. With an average response time of 137ms per request, it's almost twice as fast as loading directly from S3, and slightly faster than loading directly from the server.
I suspect that error is relevant with the CORS options of your request.
With jQuery, this is currently my sample code that successfully uploading file to S3 via CloudFront (notice the crossDomain
option). If you don't use jQuery, you can base on this to write your code:
$.ajax({
type: 'POST',
url: 'YourGetSignatureMethod', //return your signed url
data: {
fileName: yourFileName,
expiration: yourPolicyExpirationDate
},
success: function (signedUrl) {
//signedUrl= 'http://sampleId.cloudfront.net/video.mp4?Policy=examplePolicy&Signature=exampleSignature&Key-Pair-Id=exampleKey'
let fileObject = yourGetFileFunction(); //returns File API
let reader = new FileReader(); //using the FileReader API to read files
reader.onload = function () {
$.ajax({
url: signedUrl,
type: 'PUT',
contentType: fileObject.type,
data: reader.result,
processData: false,
crossDomain: true,
success: function(){
//upload success
}
});
}
reader.readAsArrayBuffer(fileObject);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With