To show a minimal example for uploading images in the same API call as your form data for creating a table entry in your database and storing an image online. The demo is not meant to be all encompassing and meet the various situations and one-off needs that come with image handling between the client and the server.
- Express
- Handlebars
- AWS S3 Bucket
- Clone repo to local computer.
git clone https://github.com/michaelmcshinsky/file-upload-demo.git
cd file-upload-demo
- Setup .env file from .env.example 2.1 You will need your KEY and SECRET from AWS
- Create local database with the same name from your .env file.
- Install packages.
yarn install
ornpm install
- Run the demo.
yarn start
ornpm start
.
There is a lot of architecural code in the demo for scaffolding out a working demo. The files of note that would be of most interest are:
Uploading of the image from the frontend.
/views/create.handlebars
/public/js/create.js
Storing image and table rows in S3 and server database.
/routes/api/posts.js
/utils/file-service.js
Features which should be considered when expanding upon this example.
- Folder structure in the S3 Bucket. Allocating images to unique folders based on user, product, post, etc...
- Image tranformation. One or many images sizes stored/altered. What is the maximum upload size.
- Upload validation. If the table creation fails, destory the image stored, or wait until entity creation success before completing image storage.
- Image validation. What kind of image types (png, jpg, etc...) are accepted.
- Business rules behind image acceptance could include rating of image (PG, PG-Y7, PG-13, R, NSFW, etc...). This may require a image learning and checking system.
- Upload avenues. Currently only one way to upload an image with strict acceptance criteria on propery name. This could be made more dynamic and DRY.
- CDN. Ability to tie S3 with a CDN and reduce distibution costs.
You should make your permissions more verbose and locked down as needed than this example.
Change BUCKET_NAME
to your bucket's name.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:GetObjectAcl"
],
"Resource": "arn:aws:s3:::BUCKET_NAME/*"
}
]
}