This repository contains the Node.js, HTML, JavaScript, and supporting jQuery plugins to upload images securely to S3 using Amazon API Gateway and AWS Lambda to generate a signed upload url.
You can find a demo online at ImageUpload.SamMart.in (images are deleted automatically almost immediately).
This example project is simply an exercise for me (Sam Martin) to dabble in:
- AWS Lambda
- Amazon API Gateway
- Basic CSS, JS, and HTML linting with Travis CI
The execution workflow is extremely simple. From loading the page in the browser:
- User selects a file to upload
- JavaScript calls out to the API Gateway endpoint using jQuery's
$.post
to retrieve a signed upload URL - API Gateway calls the Lambda Node.js script
- Node.js script assumes the IAM role associated with it which has permission to upload an object to the s3 bucket
- Node.js uses the inbuilt AWS SDK to
getSignedUrl
and returns it in itscontext.done
- This url is returned to the client-side JS via API Gateway and is then used to upload a file using BlueImp's jQuery File Upload
After whipping up this example I discovered it was actually possible to do this using signed url policies (I didn't previously appreciate that the signature validated the policy).
This removes the need to involve either Lambda or the API Gateway (more info here, JS example here), and actually provides more functionality.
However, this was still a useful learning experience, and with this methodology you are able to maintain control over the key name, which you aren't with the above example. (Though admittedly not being able to control the max upload size server side is a pretty big downside!)
I also want to add in support for user authentication at some point using Amazon Cognito which will make better use of the API Gateway and Lambda services.
- BlueImp's jQuery File Upload for uploading
- Twitter BootStrap for styling
- AWS SDK (built into Node.js)
- JSHint for JavScript linting
- PrettyCSS for CSS linting
The continuous integration portion of this dabbling is currently limited to JS and CSS linting using JSHint
and PrettyCSS
respectively.
ToDo
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1440938489000",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::image-upload-smartin",
"arn:aws:s3:::image-upload-smartin/*"
]
}
]
}
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::image-upload-smartin/*"
}
]
}
Author:: Sam Martin (samjackmartin@gmail.com)