Handling file input from client in the server is a very important part of both web and software development. Ranging from handling profile images of your users to handling pdf documents containing any important info about your users.
For long, anytime a project got to the stage of receiving files from the client side, I saw it as strange.
I tried avoiding it but I found out it was something I could not just run away from as a web developer.
In the post I showed everything you must know about file upload in Node.js.
By the end of this post you should know how to upload files from the client side, receive it properly and work with the file in your Node.js server. Won't that be great 🤗🤗
Steps To Uploading Files
- Create your Node.js project folder
- Install necessary modules
- Create a simple Node.js server with Express
- Create Html file which client will use in uploading files
- Serve Html file from the Node.js server to the client
- Create Route for receiving the files
- Create location for storing files in server and setting restrictions to these files using multer
- Pass the received file to Multer from the route created in step 6
Each step will is explained below
I will be writing the codes in snippets and at the end of the post you will see the whole code in one place 😎😎.
Prerequisites
It is expected that you have node installed on your computer and it is up and running else click here and when you are done you can continue with the post.
You should have had basic knowledge of express. How to create a route for any request method (GET, POST, PUT, DELETE)
If you met the above requirements, let's jump right in and rock 🥳🥳.
1. Creating Your Node.js Project Folder
⚠ Before we start, I want you know that every file are made up of bytes and its only the extension name that determines how the computer reads these files.
So create a folder and name it "upload"
Go to the directory of the folder in you terminal and type the following command in order to create a node project
USER@User MINGW64 ~/Desktop/upload
$ npm init -y
This will create a node.js project with a file "package.json" in the folder
2. Installing Necessary Modules
We will use Node Package Manager (npm) to install the 2 modules we will be using for the simple project.
- multer
- express
In your command line, install the above modules
npm install multer express
This will add the modules to the node modules folder in your project directory.
3. Creating Simple Node.js Server with Express
Create a file in the directory with name as "app.js"
In the file type or paste the below code into it
// Include the express module into the poject for creating the server
const express = require("express")
// Include the multer module into the project for accepting files
const multer = require("multer")
// Include the path module (It is built-in and so need to install)
const path = require("path")
// Path module will be used to get extension name of every file entering the server
// We will set the object received from the express() function to a variable "app"
const app = express()
// Set a port on which the server will run on
const port = 3000
// Create the server and let it run on the port 3000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
Run the server code from the terminal
// Run the server form the terminal
$ node app.js
// Server is running on port 3000
From your browser, make a request to the server using localhost:3000.
This means that our server is up and running but do not have any route to receive any request I make to the server.
4. Create Simple HTML for sending files to the server
The next thing to do, will be to create an HTML file through which users can send files to your Node.js server.
In the same directory, create a folder named "public" and in the folder create a file named "index.html"
Paste the HTML text below into the file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
</head>
<body>
<div class="container">
<h1>File Upload</h1>
<!--Create a form to send the file to a route "upload"-->
<!--Set the request method to POST-->
<!--Set the encytype to "multipart/form-data" in order to send files and not just text-->
<form action="/upload" method="POST" enctype="multipart/form-data">
<div class="file-field input-field">
<div class="btn grey">
<input type="file" name="myImage">
</div>
</div>
<button class="btn" type="submit">Submit</button>
</form>
</div>
</body>
</html>
After creating the file, the next question should be "How will you show the users this HTML file for them to insert their files?" 🤷♂️🤷♂️.
5. Serve the HTML file From The Server Once A Request Is Made
At the top of your code in "app.js", insert the code below
app.use(express.static("public"))
// Server will render the html file in the public folder which is index.html
The above line of code will tell express to serve anything to the client from the "public" folder
In your terminal restart the app by press "Ctrl+C" for windows and "Cmd+C" on Mac and typing in node app.js
Now make a request from your browser
You should see the html file rendered 🥳🥳
6. Create Route For Receiving Files From The User
Now that the user can upload files from the browser, we will have to create a route to recieve these files in the server.
In your app.js
, add the POST
route to receive the file
app.post("/upload", (req, res) => {
// This is the response sent to the user in the browser once the file recieved
res.send("Hello World")
})
If you send a file from the browser to the server, you will see a response of "Hello World"
And now that the user is getting a response, the next thing to do will be to handle these files in our server.
We will stores the files and even validate them 😎😎.
7. Create Location For Storing These Files With Multer
Here I will show you how to set restrictions to the type of file coming into your server .
I guess as developer, you wouldn't want to receive pdfs into your server when you need images or would you ? 🤷♂️🤷♂️.
However, with the multer object we will create a location for storing the files.
The multer object has 3 main options passed to it.
storage and dest
fileFilter
-
limits
Storage and dest
They are used to set the storage location for the file in your server but
storage
gives you more options. e.g to reset the name of the file in the server.while
dest
just sets the location for storing the file and nothing else.In this I will be using
storage
.fileFilter
This is used to control file type coming into the server.
⚠ Never trust file input from clients and so you must always validate the type of file to avoid people injecting codes into your server.
limits
It is used to set limit to either number of files, file size or any other property of files coming into the server
Read through the lines of code and paste at the top section of your code in "app.js"
const upload = multer({
storage: multer.diskStorage({
destination: "/upload/images", // Storage location
filename: (req, res, (cb) => {
cb(null, Date.now() + path.extname(file.originalname)) // return a unique file name for every file
})
}),
limits: {fileSize: 20000000}, // This limits file size to 2 million bytes(2mb)
fileFilter: (req, file, cb) => {
const validFileTypes = /jpg|jpeg|png/ // Create regex to match jpg and png
// Do the regex match to check if file extenxion match
const extname = validFileTypes.test(path.extname(file.originalname).toLowerCase())
if(extname === true){
// Return true and file is saved
return cb(null, true)
}else{
// Return error message if file extension does not match
return cb("Error: Images Only!")
}
}
}).single("myImage")
At the top of the code, I set the storage location to a folder "upload/images" which is in the public folder and I set the file size limit to 20000000 bytes (2mb).
And right at the bottom of the code I did a regex match (I will publish a post on regex very soon) to ensure that all files coming in had an extension of either "png", "jpg" or "jpeg".
Once all these are in place, the next we will do will be to pass these files into this variable "upload". "upload" is like an instance of multer class.
8. Pass the received file to Multer from the route created in step 6
At the route where the POST
request is made, add the update
variable and pass users request into it.
app.post("/upload", (req, res) => {
// This is the response sent to the user in the browser once the file recieved
upload(req, res, (err) => {
if(err){
res.send(err)
// This will display the error message to the user
}
else{
res.send("File Uploaded Successfully")
// This shows the file has beem successfully uploaded
// The image will be found in the public folder
}
})
})
With the above code when you send image files from the browser to the server, they are stored in the set location "upload/images" else the err
message is displayed on the browser.
And finally we have come to the end 🥳🥳
Full code for "app.js"
// Include the express module into the poject for creating the server
const express = require("express")
// Include the multer module into the project for accepting files
const multer = require("multer")
// Include the path module to extract file extension from every file entering the server.
const path = require("path")
// We will set the object received from the express() function to a variable "app"
const app = express()
// Set a port on which the server will run on
const port = 3000
const upload = multer({
storage: multer.diskStorage({
destination: "/upload/images", // Storage location
filename: (req, res, (cb) => {
cb(null, Date.now() + path.extname(file.originalname))
// return a unique file name for every file
})
}),
limits: {fileSize: 20000000},
// This limits file size to 2 million bytes(2mb) fileFilter:
fileFilter: (req, file, cb) => {
// Create regex to match jpg and png
const validFileTypes = /jpg|jpeg|png/
// Do the regex match to check if file extenxion match
const extname = fileTypes.test(path.extname(file.originalname).toLowerCase())
if(mimetype && extname){
// Return true and file is saved
return cb(null, true)
}else{
// Return error message if file extension does not match
return cb("Error: Images Only!")
}
}
}).single("myImage")
app.post("/upload", (req, res) => {
// This is the response sent to the user in the browser once the file recieved
upload(req, res, (err) => {
if(err){
res.send(err)
// This will display the error message to the user
}
else{
res.send("File Uploaded Successfully")
// This shows the file has beem successfully uploaded
// The image will be found in the public folder
}
})
})
// Create the server and let it run on the port 3001
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
Well, that's it! I have certainly learnt a lot from writing this down. I will be happy to answer questions in the comments 🤗🤗.
My next post will be how we can store these files into our database (MongoDB) instead of our server system to avoid over loading it.
Don't forget to like and share if you enjoyed and learnt something new from the post 🤗🤗.
Top comments (6)
Hi. how can I do this in MVC?
Thanks. I wonder if Multer process request that is sent without a form?
Hello Dory,
I don't think it is possible but if you find anyway of doing such I would be glad to hear it 🤗🤗
Thanks soo much man!, this was life saving, made the post immediately I needed it.
I love the way you explain things, keep it up...
I am glad you liked it 😊😊😊.
How to store the photo using the xampp database server.?