DEV Community

Graita Sukma Febriansyah Triwildan Azmi
Graita Sukma Febriansyah Triwildan Azmi

Posted on • Edited on

2

Express file upload using Multer

API with upload
When you are developing an API (Application Programming Interface) there must be a requirement which allows users to be able to upload or download file. A simple example of this implementation is the user able to change his picture profile. In this case, data sent by the user is not JSON (Javascript Object Notation), but the file data type. To send this data, the user has to send through the body using multipart/form data format.

What is the library to be used to create an API which able to upload or download files?

The answer to that question is Multer. Multer is one of the node.js libraries in the form of middleware which able to handle files through multipart/form data. You need to know that multipart/form data is one of content-type inside HTML form.

Multer works with adding an object body and object file to the request body. Through this, there is data containing a value from the text field and file data which is attached in HTML form.

How to create an API which able to upload and download the file in node.js?

To answer this question, we will build a simple express app which has two endpoints for uploading and downloading a file. The first step is to install the multer dependencies.
npm i express multer

Ok, before we start to write the code, we will create a folder structure like this:



src/
├── upload/
└── index.js


Enter fullscreen mode Exit fullscreen mode

Great, next we will import the required dependencies.

// Import required dependencies
const express = require("express");
const multer = require("multer");
const path = require("path");
const fs = require("fs");

Nice, now we will create multer configuration, upload function, and delete file function.

// Specifies the file upload location
const diskStorage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, path.join(__dirname, "uploads"));
},
filename: (req, file, cb) => {
cb(
null,
`${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`
);
},
});
// Create function upload with multer
const upload = multer({
storage: diskStorage,
limits: {
fileSize: 1024 * 1024 * 25, // Max file size 25MB
},
});
// Create function to delete file
const deleteFile = (file) => {
fs.unlink(file.path, (err) => {
if (err) {
console.error(err);
throw new Error("Failed to delete file");
}
});
};

You can see in the configuration section, we setting uploads folder as a file storage directory. Then we set file naming so that there are no similarities in names. On the upload function, we set diskStorage as storage and apply a file limit size of 25Mb. On the deleteFile function, we create a function which accepts one argument as the file we want to delete.

Hmm... looks like something is missing. Validation? Yup, this part is responsible to ensure the file format under the data we want.

const acceptedFileTypes = [
"image/jpeg",
"image/png",
"image/svg+xml",
"video/mp4",
"video/quicktime",
"video/webm",
"application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
];
// Membuat fungsi validasi file
const validateFileTypes = (file) => {
if (!acceptedFileTypes.includes(file.mimetype)) {
return false;
}
return true;
};

Excellent, now is the time for us to implement the configurations and functions that have been made in the route API.

// Create an express app
const PORT = 5000; // Best practice use environment variable
const HOST = "http://localhost"; // Best practice use environment variable
const app = express();
app.use(express.json());
app.post("/uploads", upload.single("file"), (req, res) => {
const file = req.file;
if (!file) {
return res.status(400).json({
message: "File not found!",
});
} else if (!validateFileTypes(file)) {
deleteFile(file);
return res.status(400).json({
message: "Unsupported file format",
});
}
return res.status(200).json({
message: "File uploaded succesfully",
data: {
url: `${HOST}:${PORT}/uploads/${file.filename}`,
},
});
});
app.get("/uploads/:filename", (req, res) => {
const file = req.params.filename;
const filePath = path.join(__dirname, "uploads", file);
if (!fs.existsSync(filePath)) {
return res.status(404).json({
message: "File not found",
});
}
return res.sendFile(filePath);
});
app.listen(PORT, () => {
console.log(`Server run on ${PORT}`);
});

Great job, now we have two routes which are uploads with HTTP method POST and uploads/:id with HTTP method GET. On the route POST, we applied a function upload.single with an argument 'file'. This 'file' is the body of the form data use to send the file. You can change the name of 'file' with others, such as 'picture'. Next, a check is applied to ensure the file is not empty and valid with our format. On the route GET, we use params :id to get the file that we want. Next, it will check whether the file exist or not.

Conclusion

To create an API which able to receive a file, we can use Multer. On the route we have created, it applied a function upload.single to accept one file. If you want to accept more than one file, you can use the function upload.array.

If you want to get this source code, feel free to take a look at this GitHub repo.

Thank you for reading this article, hope it's useful 📖. Don't forget to follow the account to get the latest information🌟. See you in the next article🙌.

Billboard image

Deploy and scale your apps on AWS and GCP with a world class developer experience

Coherence makes it easy to set up and maintain cloud infrastructure. Harness the extensibility, compliance and cost efficiency of the cloud.

Learn more

Top comments (0)

The best way to debug slow web pages cover image

The best way to debug slow web pages

Tools like Page Speed Insights and Google Lighthouse are great for providing advice for front end performance issues. But what these tools can’t do, is evaluate performance across your entire stack of distributed services and applications.

Watch video

Retry later