mkdir uploader && cd uploader
npm init -y
The first line creates an empty directory and moves into it. A new NodeJS project is initiated in this directory.
A package.json
file is created with the default details.
The package.json
file should look just like this:
{
"name": "uploader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
This configuration takes the name from the folder name. It also assumes that we have an index.js
file as our main file.
Create a new index.js
file and put the following code in it:
// Import dependencies
const express = require('express')
const app = express()
var bodyParser = require('body-parser')
// Set port
const port = 3000
// Register middlewares
app.use(bodyParser.urlencoded({ extended: false }))
// Home route
app.get('/', (req, res) => {
res.send('Hello World!')
})
// Start listening
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
This file is our main application file. It requires a few dependencies that can be installed using:
npm i body-parser express
npm i -D nodemon
The first dependency, body-parser
, is a middleware that adds the request data to the request. The dev dependency nodemon
restarts the server whenever a change is made to the code, which ensures that the server is always running.
Now you have a new ExpressJS server ready to go. Run the server using nodemon.
nodemon index.js
Now the server is active and can listen for requests.
You can test by visiting
http://localhost:3000
on your browser.
Next, to handle file upload, a file has to be uploaded. To upload a file, an HTML form can be used.
Create an index.html
file in the directory, at the same level as our main file, index.js
, and add in the following content:
<!doctype html><html lang="en"><head><!-- Required meta tags --><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><!-- Bootstrap CSS --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous"><title>Hello, world!</title></head><body class="container"><form class="card m-5 mx-auto p-5" action="/upload" method="POST" enctype="multipart/form-data"><!-- Username --><div class="mb-3"><label for="username" class="form-label">Your Name</label><input type="text" class="form-control" name="username"></div><!-- Image File --><div class="mb-3"><label for="image" class="form-label">Image</label><input type="file" class="form-control" name="image"></div><button type="submit" class="btn btn-primary">Submit</button></form></body></html>
This file uses the starter template from the Bootstrap website. The page has a text input and a file input to upload the target file. Update the index.js
file to render this view:
app.get('/', (req, res) => {
// Render form view
res.sendFile(__dirname + '/index.html')
})
This route now renders the newly created HTML file, accessing it using its relative path.
Visiting the page again returns a view like this:
Notice how you do not have to manually restart the server; nodemon
restarts it when you save new changes. So, as long as the server was started as stated in Step 1, it should still be running.
Next, when the form is submitted, we want to receive the file. This involves a few steps.
First, create an endpoint to receive the form request.
// Image processing route
app.post('/upload', (req, res) => {
res.send('Submitted')
})
At this point, the form only prints the text 'Submitted'
when submitted. Test this by actually submitting the form.
In earlier versions of ExpressJS, files can be accessed easily as part of the request object using req.files
. In recent versions, this property is no longer available on the request object. Now, you can use multer, a separate package, to access uploaded files.
Install multer
:
npm i multer
Instantiate multer
in the index.js
file:
// Import multer like the other dependencies
const multer = require('multer')
// Set multer file storage folder
const upload = multer({ dest: 'uploads/' })
Here, we import multer
and instantiate it by telling it where to store all uploaded files.
To use multer
, add the middleware to the endpoint:
app.post('/upload', upload.single('image'), (req, res) => {
console.log(req.file)
})
The middleware adds a file
property to the request object. This property will only have some value if the name of the file input in the form matches the name it expects.
In this case, it expects the file name to be image, as shown in upload.single('image')
. The middleware also stores the uploaded file in the stated uploads
folder.
Testing this current logs the uploaded file, and it has the following structure:
{
fieldname: 'image',
originalname: 'Screenshot 2021-11-02 at 00.12.28.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'uploads/',
filename: 'a15af77a31eb44b4a6b043db90f15214',
path: 'uploads/a15af77a31eb44b4a6b043db90f15214',
size: 538524
}
At this point, you now have access to the file using req.file
and all these properties by adding the property name to req.file
using object notation. For example, to see the file path, use req.file.path
.