-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add aws-node-upload-to-s3-and-postprocess
Example to demonstrate how to upload a file to S3 using a HTML form, and have an S3 event trigger a lambda function. fixes #16
- Loading branch information
1 parent
044adb8
commit ec58bd9
Showing
8 changed files
with
208 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
.serverless | ||
index.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Upload a file to S3 to trigger a lambda function | ||
|
||
This example shows how to upload a file to S3 using a HTML form, and have S3 | ||
trigger a lambda function. | ||
|
||
## Use-cases | ||
|
||
- Postprocess files uploaded to an S3 bucket. | ||
|
||
## Setup | ||
|
||
- Edit `serverless.yml` and choose a unique S3 bucket name. | ||
- Edit `generate-form.js` and fill in your `aws_access_key_id`, | ||
`aws_secret_access_key` and `bucket_name`. | ||
- Generate the HTML form: | ||
|
||
|
||
```bash | ||
node generate-form.js | ||
``` | ||
|
||
## Deploy | ||
|
||
In order to deploy the example, simply run: | ||
|
||
```bash | ||
serverless deploy | ||
``` | ||
|
||
The output should look similar to: | ||
|
||
```bash | ||
Serverless: Creating Stack... | ||
Serverless: Checking Stack create progress... | ||
..... | ||
Serverless: Stack create finished... | ||
Serverless: Packaging service... | ||
Serverless: Uploading CloudFormation file to S3... | ||
Serverless: Uploading service .zip file to S3 (3.85 MB)... | ||
Serverless: Updating Stack... | ||
Serverless: Checking Stack update progress... | ||
........................ | ||
Serverless: Stack update finished... | ||
Service Information | ||
service: upload-to-s3-and-postprocess | ||
stage: dev | ||
region: us-east-1 | ||
api keys: | ||
None | ||
endpoints: | ||
None | ||
functions: | ||
upload-to-s3-and-postprocess-dev-postprocess | ||
|
||
``` | ||
|
||
## Usage | ||
|
||
Open the generated `frontend/index.html` in your browser, or run: | ||
|
||
```bash | ||
xdg-open frontend/index.html | ||
``` | ||
|
||
Select a PNG image smaller than 1Mb, and click "Upload File to S3". | ||
|
||
You should get an XML response similar to: | ||
|
||
```xml | ||
<PostResponse> | ||
<Location>https://serverless-fetch-file-and-store-in-s3.s3.amazonaws.com/uploads%2Fimage.png</Location>< | ||
Bucket>serverless-fetch-file-and-store-in-s3</Bucket> | ||
<Key>uploads/image.png</Key> | ||
<ETag>"08c03c6a24e5058b9f3556981a23b1d7"</ETag> | ||
</PostResponse> | ||
``` | ||
|
||
After a while, the postprocess function gets triggerd by an S3 event: | ||
|
||
```bash | ||
serverless logs --function postprocess | ||
``` | ||
|
||
``` | ||
START RequestId: e2decc94-f2a0-11e6-b641-e3fbcfad7d8c Version: $LATEST | ||
2017-02-14 12:32:30.350 (+02:00) e2decc94-f2a0-11e6-b641-e3fbcfad7d8c New .png object has been created: uploads/image.png (23975 bytes) | ||
END RequestId: e2decc94-f2a0-11e6-b641-e3fbcfad7d8c | ||
REPORT RequestId: e2decc94-f2a0-11e6-b641-e3fbcfad7d8c Duration: 2.84 ms Billed Duration: 100 msMemory Size: 1024 MB Max Memory Used: 29 MB | ||
``` |
24 changes: 24 additions & 0 deletions
24
aws-node-upload-to-s3-and-postprocess/frontend/index.template.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<html> | ||
<head> | ||
<title>S3 POST Form</title> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||
</head> | ||
|
||
<body> | ||
<form action="%BUCKET_URL%" method="post" enctype="multipart/form-data"> | ||
<input type="hidden" name="Content-Type" value="image/png"> | ||
<input type="hidden" name="AWSAccessKeyId" value="%AWS_ACCESS_KEY%"> | ||
<input type="hidden" name="acl" value="public-read"> | ||
<input type="hidden" name="success_action_status" value="201"> | ||
<input type="hidden" name="policy" value="%POLICY_BASE64%"> | ||
<input type="hidden" name="signature" value="%SIGNATURE%"> | ||
|
||
Destination filename: <input type="text" name="key" value="uploads/image.png"> | ||
<br> | ||
File to upload to S3: | ||
<input name="file" type="file"> | ||
<br> | ||
<input type="submit" value="Upload File to S3"> | ||
</form> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#!/usr/bin/env node | ||
|
||
const crypto = require('crypto'); | ||
const fs = require('fs'); | ||
|
||
const awsAccessKeyId = '<your access key id>'; | ||
const awsSecretAccessKey = '<your secret access key>'; | ||
const bucketName = '<your bucket name>'; | ||
|
||
const msPerDay = 24 * 60 * 60 * 1000; | ||
const expiration = new Date(Date.now() + msPerDay).toISOString(); | ||
const bucketUrl = `https://${bucketName}.s3.amazonaws.com`; | ||
|
||
const policy = { | ||
expiration, | ||
conditions: [ | ||
['starts-with', '$key', 'uploads/'], | ||
{ bucket: bucketName }, | ||
{ acl: 'public-read' }, | ||
['starts-with', '$Content-Type', 'image/png'], | ||
{ success_action_status: '201' }, | ||
], | ||
}; | ||
|
||
const policyB64 = Buffer(JSON.stringify(policy), 'utf-8').toString('base64'); | ||
|
||
const hmac = crypto.createHmac('sha1', awsSecretAccessKey); | ||
hmac.update(new Buffer(policyB64, 'utf-8')); | ||
|
||
const signature = hmac.digest('base64'); | ||
|
||
fs.readFile('frontend/index.template.html', 'utf8', (err, input) => { | ||
if (err) { | ||
console.log(err); | ||
} | ||
|
||
const data = input | ||
.replace(/%BUCKET_URL%/g, bucketUrl) | ||
.replace(/%AWS_ACCESS_KEY%/g, awsAccessKeyId) | ||
.replace(/%POLICY_BASE64%/g, policyB64) | ||
.replace(/%SIGNATURE%/g, signature); | ||
|
||
fs.writeFile('frontend/index.html', data, 'utf8', (e) => { | ||
if (e) { | ||
console.log(e); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
'use strict'; | ||
|
||
module.exports.postprocess = (event) => { | ||
event.Records.forEach((record) => { | ||
const filename = record.s3.object.key; | ||
const filesize = record.s3.object.size; | ||
console.log(`New .png object has been created: ${filename} (${filesize} bytes)`); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "upload-to-s3-and-postprocess", | ||
"description": "Upload a files to S3 to trigger a lambda function.", | ||
"version": "1.0.0", | ||
"author": "Christoph Gysin <[email protected]>", | ||
"license": "MIT", | ||
"dependencies": { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
service: upload-to-s3-and-postprocess | ||
|
||
frameworkVersion: ">=1.1.0" | ||
|
||
custom: | ||
bucket: <your-bucket-name> | ||
|
||
provider: | ||
name: aws | ||
runtime: nodejs4.3 | ||
iamRoleStatements: | ||
- Effect: Allow | ||
Action: | ||
- s3:* | ||
Resource: "*" | ||
|
||
functions: | ||
postprocess: | ||
handler: handler.postprocess | ||
events: | ||
- s3: | ||
bucket: ${self:custom.bucket} | ||
event: s3:ObjectCreated:* | ||
rules: | ||
- suffix: .png |