Handling file uploads is a common requirement for web applications. Whether you're building a social media platform, admin dashboard, or CMS, being able to accept images from users is essential.
In this updated tutorial, you'll learn how to build a simple yet robust RESTful API using Node.js, Express 5, and Multer for image upload. We'll cover everything from project setup, storage configuration, image validation, to creating endpoints that accept file uploads via multipart/form-data.
By the end of this guide, you'll have a clean and modular image upload API ready to integrate into your frontend or mobile application.
Create a New Express.js Application and Required Modules
We will start this tutorial by creating or generating a web or REST API application using Express.js.
mkdir image-upload-api
cd image-upload-api
npm init -y
npm install express multer cors
Also, install nodemon as a dev dependency for easier development:
npm install --save-dev nodemon
Update package.json
to include:
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
}
Now, you are ready to create a REST API service for image upload.
Create the Main App (app.js)
Create a file at the root of the project folder.
touch app.js
Add this code:
// app.js
import express from 'express'
import cors from 'cors'
import uploadRoute from './routes/upload.js'
import path from 'path'
import { fileURLToPath } from 'url'
const app = express()
const PORT = process.env.PORT || 3000
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
app.use(cors())
app.use(express.json())
app.use('/uploads', express.static(path.join(__dirname, 'uploads')))
// Routes
app.use('/api/upload', uploadRoute)
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`)
})
Create Upload Route (routes/upload.js
)
Create a route folder and upload.js file:
mkdir routes
touch routes/upload.js
Add this code to that file.
// routes/upload.js
import express from 'express'
import multer from 'multer'
import path from 'path'
import { fileURLToPath } from 'url'
import fs from 'fs'
const router = express.Router()
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// Ensure uploads folder exists
const uploadDir = path.join(__dirname, '../uploads')
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir)
}
// Multer Storage
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, uploadDir)
},
filename: function (req, file, cb) {
const ext = path.extname(file.originalname)
const uniqueName = `${Date.now()}-${Math.round(Math.random() * 1E9)}${ext}`
cb(null, uniqueName)
}
})
// File Filter: Accept images only
const fileFilter = (req, file, cb) => {
const allowedTypes = /jpeg|jpg|png|gif/
const isValid = allowedTypes.test(file.mimetype)
if (isValid) {
cb(null, true)
} else {
cb(new Error('Only image files are allowed'), false)
}
}
const upload = multer({
storage,
limits: { fileSize: 2 * 1024 * 1024 }, // 2MB
fileFilter
})
// POST /api/upload
router.post('/', upload.single('image'), (req, res) => {
if (!req.file) {
return res.status(400).json({ message: 'No file uploaded' })
}
res.status(200).json({
message: 'Image uploaded successfully',
filePath: `/uploads/${req.file.filename}`
})
})
export default router
Run and Test the Node.js, Express.js, and Multer Image Uploader
To test this Express.js application, just run this command.
nodemon
or
npm start
Next, open the Postman application, then change the method to `POST` and the URL to `http://localhost:3000/api/upload`. Change the body to `form-data,` then fill the key as file and pick an image file. You can see the Postman request below.
You will see this response for a successful upload.
{
"fileUrl": "http://192.168.0.7:3000/images/image-1553473134646.png"
}
Now, you can check the uploaded image by entering that address from the API response.
Conclusion
In this tutorial, you’ve learned how to build a modern RESTful image upload API using Node.js, Express 5, and Multer. You’ve covered setting up the project, configuring file storage, filtering and validating uploaded images, and handling uploads via an HTTP POST endpoint.
This API serves as a solid foundation for many real-world use cases — from user profile photo uploads to content management systems or e-commerce product images. You can easily extend this by adding:
-
File type restrictions or virus scanning
-
Cloud storage integration (e.g., AWS S3, Cloudinary)
-
Image resizing and optimization (e.g., using Sharp)
-
Authentication and access control
With the growing demand for image handling in modern apps, mastering this kind of API development is an essential backend skill.
You can get the full source code from our GitHub.
That's just the basics. If you need more deep learning about MEAN Stack, Angular, and Node.js, you can take the following cheap course:
- Angular (Angular 2+) & NodeJS - The MEAN Stack Guide
- Start Building Web Apps And Services With Node. js + Express
- Build a REST API with Node. JS, ExpressJS, and MongoDB
- Angular 5 Bootcamp FastTrack
- Angular 6 - Soft & Sweet
- Angular 6 with TypeScript
Thanks!