How To Upload Image and Retrieve URL of the Uploaded Image Using React JS and Node JS
By: Basil Kaffi Ar Rahman
Tags: Nodejs, Expressjs, Reactjs, Multer

In this tutorial we will learn how to upload image and retrieve downloadable url of the uploaded image using React JS and Node JS. This tutorial will be made step by step so (hopefully) beginner can understand, but for someone who already get used to code, you can see a whole code in the last section of each part.

Preparing The Server

Before make react component we will prepare the server first. In here we will be using node.js as server side.

First step is make a server folder inside your project folder. Inside server folder we will create index.js and image folder to store the uploaded image later, after that we initialize npm inside it by using the command below in your terminal:

cd server

npm init -y

After all the first step finish, the result would look like this:

Second step is to install module that needed for your server, which is express.js, cors, and multer. You can install it by using command below in your terminal:

npm install express cors multer

After finish installing the modules we need to import it in index.js, we also have to configure port for our server and import path that will be used to connect multer with the prepared folder to store the uploaded image.

const express = require("express");

const multer = require("multer");

const cors = require("cors");

const path = require("path");

const app = express();

const port = 5000;

After importing the modules, we will set up middleware that our server need to run properly.

app.use(cors());

app.use(express.json());

app.use(express.urlencoded({ extended: false }));

app.use("/image", express.static("image"));

Third step is to set up our multer middleware, so our server can handle the uploaded image from client/react component.

let imageName = ""; const storage = multer.diskStorage({

destination: path.join("./image"),

filename: function (req, file, cb) {

imageName = Date.now() + path.extname(file.originalname);

cb(null, imageName);

},

}); const upload = multer({

storage: storage,

limits: { fileSize: 3000000 },

}).single("myImage");

The fourth step of preparing the server is to set up our route for API, so our client know where to upload the image, we also return image url of uploaded image to client.

app.post("/upload-image", (req, res) => {

upload(req, res, (err) => {

if (err) {

console.log(err);

} else {

return res.status(201)

.json({ url: "http://localhost:5000/image/" + imageName });

}

});

});

After all finish all we need to do is to run the server.

app.listen(port, () => {

console.log("server run in port", port);

});

Here is the whole code for the server:

const express = require("express");

const multer = require("multer");

const cors = require("cors");

const path = require("path");

const app = express();

const port = 5000; app.use(cors());

app.use(express.json());

app.use(express.urlencoded({ extended: true }));

app.use("/image", express.static("image")); ----- 11 let imageName = ""; ---- 13

const storage = multer.diskStorage({

destination: path.join("./image"), ---- 15

filename: function (req, file, cb) {

imageName = Date.now() + path.extname(file.originalname);

cb(null, imageName);

},

}); const upload = multer({

storage: storage,

limits: { fileSize: 3000000 },

}).single("myImage"); app.post("/upload-image", (req, res) => {

upload(req, res, (err) => {

if (err) {

console.log(err);

} else {

return res.status(201)

.json({ url: "http://localhost:5000/image/" + imageName }); 34

}

});

}); app.listen(port, () => {

console.log("server run in port", port);

});

Line 15 is a piece of code to set where we store the uploaded image which is folder image in server that we have made in earlier process. Line 11 is a middleware that enable us to access image folder in line 34. Line 13 is a variable name of uploaded image that will be used to call the specific image file inside an image folder. Line 34 is when we call back the specific image that recently has been uploaded and send it back to client side.

Create React Component

After server completed, now we are ready to make the react component for upload image. First thing we need to do is installing react.js outside server folder. We will use create-react-app, type command below in your terminal:

cd ..

npx create-react-app client

After folder client created, you will see something like this:

You can delete file logo.svg and all code inside App.css since we don’t need them. After that you can open file App.js, delete all element inside div with className App, and start new code there.

import "./App.css"; function App() {

return <div className="App"></div>;

} export default App;

First code we will write is a container to show our uploaded image:

import "./App.css";

import { useState } from "react"; function App() {

const [image, setImage] = useState("");

return (

<div className="App">

<h4>Image from server</h4>

<div className="imageBox">

<img src={image} width="100%"></img>

</div>

</div>

);

} export default App;

Line 5 is a variable that later on will be filled with image url that send back from server

After we create html element to contain the image, next we will style it in App.css:

.imageBox {

margin: 20px;

width: 220px;

height: 220px;

background-color: lightgray;

position: relative;

left: 50%;

transform: translateX(-50%);

}

now we can try to see it in browser, by using command below in your terminal after specify directory in client folder:

cd client

npm start

view in browser

Second code we will write is a form that contain input with file type to get image from computer and a button with submit type to upload image:

import "./App.css";

import { useState } from "react"; function App() {

const [image, setImage] = useState("");

const [imageFile, setFile] = useState(); return (

<div className="App">

<h4>Image from server</h4>

<div className="imageBox">

<img src={image} width="100%"></img>

</div>

<hr></hr>

<h4>Image Preview</h4>

<form>

<input type="file"></input>

<button type="submit">upload</button>

</form>

</div>

);

} export default App;

Line 6 is a variable for contain our image file

let’s see how it looks in browser, and test if input file can open file explorer:

successfully open file explorer by clicking choose file (input type file)

After write form code, we need to write logic to upload the image, but before that we need to install axios module and import it on App.js so we can connect to server:

npm install axios

Now we will write the logic code:

Save chosen image from computer to variable imageFile

import "./App.css";

import { useState } from "react";

import axios from "axios"; function App() {

const [image, setImage] = useState("");

const [imageFile, setFile] = useState(); const getImage = (e) => {

setFile(e.target.files[0]); //save chosen image to imageFile

} return (

<div className="App">

<h4>Image from server</h4>

<div className="imageBox">

<img src={image} width="100%"></img>

</div>

<hr></hr>

<h4>Image Preview</h4>

<form>

<input type="file" onChange={getImage}></input>

<button type="submit">upload</button>

</form>

</div>

);

} export default App;

2. Upload imageFile to server

import "./App.css";

import { useState } from "react";

import axios from "axios"; function App() {

const [image, setImage] = useState("");

const [imageFile, setFile] = useState(); const getImage = (e) => {

setFile(e.target.files[0]);

} const uploadImage = (e) => {

e.preventDefault() //prevent browser to refresh

const formData = new FormData(); //create new form object

formData.append("myImage", imageFile);//add image to form object

axios({

method: "post",

url: "http://localhost:5000/upload-image",

data: formData, //send image to server

})

.then((response) => {

const { data } = response; //return image url of uploaded img

setImage(data.url); //set url to image variable

})

.catch((err) => {

console.log(err);

});

} return (

<div className="App">

<h4>Image from server</h4>

<div className="imageBox">

<img src={image} width="100%"></img>

</div>

<hr></hr>

<h4>Image Preview</h4>

<form onSubmit={uploadImage}>

<input type="file" onChange={getImage}></input>

<button type="submit">upload</button>

</form>

</div>

);

} export default App;

Now let’s try to upload an image:

upload image is success and it return back url of image that used as src in tag <img>

3. Create image preview container

import "./App.css";

import { useState } from "react";

import axios from "axios"; function App() {

const [image, setImage] = useState("");

const [imageFile, setFile] = useState();

const [imagePreview, setPreview] = useState(); const getImage = (e) => {

setFile(e.target.files[0]);

} const uploadImage = (e) => {

e.preventDefault()

const formData = new FormData();

formData.append("myImage", imageFile);

axios({

method: "post",

url: "http://localhost:5000/upload-image",

data: formData,

})

.then((response) => {

const { data } = response;

setImage(data.url);

})

.catch((err) => {

console.log(err);

});

} return (

<div className="App">

<h4>Image from server</h4>

<div className="imageBox">

<img src={image} width="100%"></img>

</div>

<hr></hr>

<h4>Image Preview</h4>

<form onSubmit={uploadImage}>

<div className="imageBox">

<img src={imagePreview} width="100%"></img>

</div>

<input type="file" onChange={getImage}></input>

<button type="submit">upload</button>

</form>

</div>

);

} export default App;

Line 8 is variable to contain image url preview

let’s see what’s in the browser:

4. Hide input type file, add new button to replace it, and set image Preview (whole code of react component)

import "./App.css";

import { useState, useRef } from "react";

import axios from "axios"; function App() {

const [image, setImage] = useState("");

const [imageFile, setFile] = useState();

const [imagePreview, setPreview] = useState();

const inputEl = useRef(null); //variable to referring hidden input const getImage = (e) => {

setFile(e.target.files[0]);

setPreview(URL.createObjectURL(e.target.files[0]));//set preview

} const uploadImage = (e) => {

e.preventDefault()

const formData = new FormData();

formData.append("myImage", imageFile);

axios({

method: "post",

url: "http://localhost:5000/upload-image",

data: formData,

})

.then((response) => {

const { data } = response;

setImage(data.url);

})

.catch((err) => {

console.log(err);

});

} return (

<div className="App">

<h4>Image from server</h4>

<div className="imageBox">

<img src={image} width="100%"></img>

</div>

<hr></hr>

<h4>Image Preview</h4>

<form onSubmit={uploadImage}>

<div className="imageBox">

<img src={imagePreview} width="100%"></img>

</div>

<input type="file"

onChange={getImage}

style={{display: "none"}} //hiding input

ref={inputEl} //set inputEl to referring this element

></input>

<button

onClick={() => inputEl.current.click()}

>select image</button>

<button type="submit">upload</button>

</form>

</div>

);

} export default App;

Here is the complete look of the code:

image above is old uploaded image and image below is a preview of new image that will be uploaded

Okay, that’s all I can share about this tutorial, I hope this can be useful for your project.