How to build an API for image upload in Node js

Learn how to handle image upload in Node.js and React.js by building, and using an API.

author profile image
Sakchhyam G
@sakchhyam

Share

How to build an API for image upload in Node js

Table of content

  1. Setting up the Server app - Node and Express
  2. Writing some utility functions
  3. Writing logic for the upload route
  4. Using API in the client app - React
  5. Conclusion

Setting up the Server app - Node and Express

Dependencies

Create a node project or use the existing one. In your Node project, install the following packages express, cors, and express-fileupload. We will use the express-fileupload package to handle the image upload request. Besides, we will also use the cors package to allow cross-origin request-response in our project.

Run the code snippet below to install the dependencies:

npm install -save express cors express-fileupload

Creating the server app

In the code snippet below, we are creating an express app and listening to port 5000 for our request.

1// index.js 2const express = require("express"); 3const cors = require("cors"); 4 5const app = express(); 6// Parsing the request body 7app.use(express.json()); 8app.use(express.urlencoded({ extended: false })); 9// Enabling CORS requests for all routes 10app.use(cors()); 11 12app.get("/api/", (req, res) => { 13 res.status(200).send("Everything is working"); 14}); 15 16app.listen(5000, () => { 17 console.log(`Server running at PORT:5000`); 18});

The server file structure looks like this:

  node_modules
  index.js
  package-lock.json
  package.json

Running the server app

Open terminal in our project root and run the command to run the Node app: npm run server

Now open a browser and type this URL: localhost:5000/api/. Here localhost:5000 is our hostname, and /api/ is an end-point that handles our get request. Check if you get the message "Everything is working" in your browser.

Writing some utility functions

In your Node project, create a util.js file. In this file, we will write some helper functions for our upload API like image-name generator, and image-path generator. Now add the below code for utility functions.

1const path = require("path"); 2 3function imgNameGen(imgName) { 4 return new Date().getTime() + "_" + imgName; 5} 6 7function imgPathGen(directory, imgName) { 8 return path.join(__dirname, directory + `${imgName}`); 9} 10 11module.exports = { imgNameGen, imgPathGen };

Writing logic for the upload route

In your root folder, create an upload/images directory. In this directory, the image upload API will store the image uploads. Finally, in our index.js file, add the following code for the image upload route.

1// index.js 2const express = require("express"); 3const cors = require("cors"); 4const fileUpload = require("express-fileupload"); 5const { imgNameGen, imgPathGen } = require("./util"); 6 7const app = express(); 8app.use(fileUpload()); 9// Parsing the request body 10app.use(express.json()); 11app.use(express.urlencoded({ extended: false })); 12// Enabling CORS requests for all routes 13app.use(cors()); 14 15app.get("/api/", (req, res) => { 16 res.status(200).send("Everything is working"); 17}); 18// Image upload route 19app.post("/api/upload/image", (req, res) => { 20 // Checking for 'files' key in request object 21 if (!req.files || Object.keys(req.files).length === 0) { 22 return res.status(400).send("No files were uploaded."); 23 } 24 // Holds urls of images uploaded in the server 25 const imgURL = []; 26 // For multiple image upload 27 if (Array.isArray(req.files["images[]"])) { 28 req.files["images[]"].forEach((img) => { 29 const imgName = imgNameGen(img.name); 30 const imgPath = imgPathGen("/upload/images/", imgName); 31 imgURL.push(imgName); 32 // moves uploaded images to the './upload/images' directory in server 33 img.mv(imgPath, (err) => { 34 if (err) { 35 console.log("err", err); 36 return res.status(500).send(err); 37 } 38 }); 39 }); 40 } else { 41 // For single image upload 42 const imgName = imgNameGen(req.files["images[]"].name); 43 const imgPath = imgPathGen("/upload/images/", imgName); 44 imgURL.push(imgName); 45 46 req.files["images[]"].mv(imgPath, (err) => { 47 if (err) { 48 console.log("err", err); 49 return res.status(500).send(err); 50 } 51 }); 52 } 53 54 res.status(200).send({ imgURL }); 55}); 56 57app.listen(5000, () => { 58 console.log(`Server running at PORT:5000`); 59});

The final server file structure looks like this:

node_modules
├─ upload/
│  ├─ images
│  │  ├─ //... images.jpeg
index.js
package-lock.json
package.json
util.js

Using API in the client app - React

In the next step, we will use the API in the client app we built in the previous article. To make an API call we will use Axios. So, install the package using: npm install axios --save

In src folder, create an img-upload-api.js file and add the following code to make the API call:

1import axios from "axios"; 2 3const apiBase = "http://localhost:5000/api"; 4 5export async function uploadImage(formData) { 6 try { 7 const { data } = await axios.post(`${apiBase}/upload/image`, formData); 8 return data; 9 } catch (error) { 10 console.log("Image upload error: ", error); 11 } 12}

In the App.js file, add the additional code to submit the images. The FormData class will create a new form object. We will attach the image URLs to the form object and then send it to the server side using the post method of the API.

1import { useState } from "react"; 2 3import "./styles.css"; 4import ImageUpload from "./components/ImageUpload"; 5import { uploadImage } from "./img-upload-api"; 6 7export default function App() { 8 const [selectedImages, setSelectedImages] = useState([]); 9 10 const handleSubmit = () => { 11 if (selectedImages.length === 0) { 12 alert("Pick at least one image."); 13 } 14 const uploadedImages = new FormData(); 15 16 selectedImages.forEach((img) => { 17 uploadedImages.append("images[]", img); 18 }); 19 20 uploadImage(uploadedImages).then((res) => { 21 console.log("Response after submitting image:", res.imgUrl); 22 //Use imgUrl according to need 23 setSelectedImages([]); 24 }); 25 }; 26 27 return ( 28 <div className="App"> 29 <h1>Image Upload in React</h1> 30 31 <ImageUpload selectedImages={selectedImages} setSelectedImages={setSelectedImages} /> 32 <div className="submitBtn" onClick={() => handleSubmit()}> 33 Submit 34 </div> 35 </div> 36 ); 37}

Now, make sure both client and server program is running. Open the client (React) app in the browser, upload some images, and check the imgUrl in the response. This urls can be used to retrieve the images from the server.

The final client folder structure looks like this:

src/
├─ components/
│  ├─ ImageUpload.js
│  ├─ ImageUpload.module.css
├─ App.js
├─ img-upload-api.js
├─ index.js
├─ styles.css

Conclusion

In this article, we learned to build a route to handle basic image upload in Node. You can use similar logic and packages in other languages and platforms too.

We can improve the above program by adding additional features like

  • checking the image size and format on the server side (Node)
  • adding authentication middleware in the route
  • apply similar logic for other media formats

Thanks for reading this article. Don't forget to check out my other articles. You can support this article by sharing it.

Advertisement
Advertisement