Upload on AWS S3 with Express.js and Vue.js - Part 1
I’m refactoring my favorite side project.
Part of this relies on how the file-upload works both on the backend and frontend as well.
In PRESENTA the external files are uploaded using AWS S3 service. The real upload happens straight from the front-end app to the AWS servers. The backend is in charge only to request the one-time token from AWS. Here the flow:
- The frontend asks to the backend a valid token (this way the backend can make some additional validation about auth and other stuff)
- The backend asks to AWS the same and routes it to the frontend
- The frontend begins a PUT request to AWS server to upload the files
- The dialogue during the upload happens only between the frontend and the S3 service
The backend #
In this tutorial, I’m explaining the backend code that is an Express.js based app. The dependencies (that need to be installed) are:
- express
- cors
- dotenv
- aws-sdk
Here the minimal Express app:
const express = require('express')
const path = require('path')
const app = express()
const port = process.env.PORT || 3131
app.listen(port, () => console.log('Server is running on port: ' + port))
Set-up the CORS #
We need a nice dialogue between the backend and the frontend, therefore, we enable the CORS communication with:
const cors = require('cors')
var origins = {
origin: ['http://localhost:8080'],
optionsSuccessStatus: 200,
credentials: false
}
app.use(cors(origins))
Auth with AWS #
Here the authentication with S3 using your personal credentials:
const aws = require('aws-sdk')
aws.config.region = 'eu-west-3'
const S3_BUCKET = process.env.S3_BUCKET_NAME
The route #
In this little webserver contains only one route with comments between the lines
app.get('/s3', (req, res) => {
// get the params from the initial request
const fileName = req.query.filename
const fileType = req.query.filetype
const ext = path.extname(fileName)
// define the location and the file name
const pathName = path.join('myfoldertest', 'myuploadedfile' + ext)
const s3 = new aws.S3()
// configure the S3 object to get the token
const s3Params = {
Bucket: S3_BUCKET,
Key: pathName,
Expires: 60 * 15,
ContentType: fileType,
ACL: 'public-read'
}
// ask for the token
s3.getSignedUrl('putObject', s3Params, (err, data) => {
if (err) {
return res.status(500).json(err)
}
const returnData = {
signedRequest: data,
url: `${pathName}`
}
// returning the token to the frontend
res.status(200).json(returnData)
})
})
This little server can be run with node index.js and it will listen at http://localhost:3131/s3 with the filename and the filetype parameters correctly set.
This is a bare-bone example without many error handling, just to demonstrate this particular functionality. Full source code here.
In part 2 I’ll dive in the frontend part, of course.
Stay tuned.