React File Uploader With Express (Using React Hooks)

React File Uploader With Express (Using React Hooks)

Welcome folks I am back with another blog post. In this blog post we will be making a React File Uploader Application with Express server running in the backend. And also in the process we will be using the concept of React Hooks which will be useful in uploading files in our application. Let’s get started with the application.

 

First of all we will making the backend of the application. So first of all we will installing express and making the server.

 

Making Backend

 

Create a brand new directory where you will create your project files and move in to the directory and open command prompt. For this application you should have node installed on to your system. Just write this command npm init -y on cmd. So this will create the package.json file for the project.

 

 

Now we will install the required dependencies for the creating the backend of the application. So first of all we need express for creating the server, and secondly we also need express-fileupload which is nice little library in express to create a file uploader functionality in express. So we will install these two dependencies.

 

 

 

Now we also need two dev dependencies for this project which are nodemon and concurrently. Nodemon will actually restart the server when any kind of changes are made to the application and concurrently will actually us to run express server and react server at the same time.

 

 

 

After installing these dependencies the package.json file will look something like this

 

 

 

Now after this we need to add some scripts in the scripts block so that we can run both the servers at the same time express and react. Just copy paste this lines exactly in the script block of your package.json file as shown below.

 

"scripts": {
    "start": "node server.js",
    "server":"nodemon server.js",
    "client":"npm start --prefix client",
    "dev":"concurrently \"npm run server\" \"npm run client\""
  }

 

Now the package.json file after adding these scripts will look something like this as shown below.

 

 

 

Now we will create the server.js file which will actually start the express server for us. In this file first of all we will be importing all the dependencies that we have installed earlier. i.e. express , express-fileuploader and then we will be initializing express and store the reference in app variable. And after that we will be binding the express file uploader middleware on the app variable. And then we will start the server on 5000 port number by calling the listen method on app variable and in the second argument it takes the callback function in which we can simply print in the console a message that the server is running on 5000 port number.

 

const express = require('express');

const fileUpload = require('express-fileupload');

const app = express();

app.use(fileUpload());

app.listen(5000, () =>{

    console.log("Server started on Port Number 5000");

})

 

Now we will configure the routes for the express server. The only route we need to configure for this express server is the post request to the /upload url as shown below. The code to configure this route is given below.

 

app.post('/upload',(req,res) =>{
    if(req.files === null)
    {
        return res.status(400).json({msg:"No file was uploaded"});
    }
    const file = req.files.file;

    file.mv(`${__dirname}/client/public/uploads/${file.name}`,err =>{
        if(err){
            console.log(err);
            return res.status(500).send(err);
        }
        res.json({fileName:file.name,filePath:`/uploads/${file.name}`});
    })
})

 

Explanation of this Code

 

1) In the first few lines of code we are configuring the post request to the url /upload and then it takes the callback function request and response and then we check if the request contains the files or not. If the request doesn’t contain any files or it is null then we can simply send the 400 status code along with the json response that no file was uploaded.

2) Secondly we are handling the case whenever the request contains the file to upload then we are first of all fetching the file to upload and then we are using the move function that we are invoking on the file variable and in this function we are passing the template string containing the full address or path of the uploaded image. And second argument is the err callback function. We check for the error if any kind of error is there then we are printing that error on the console and also returning the status code of 500 and also sending the actual error back to the client.

READ  Login with Instagram using Javascript

3) And lastly if no error is there with the file then we are sending the json response to the client which contains the file name and the actual full path of the uploaded file.

 

Now if we run the express server by typing the command npm run server as shown below then we can see that nodemon is running our server and actually this is all we want in the backend. So the backend part is complete. After this we will now move to building the frontend ie. react.

 

 

 

Making FrontEnd

 

Now we will be make our frontend of the application. Just type this command on the command prompt to make a new React Application in a new folder called as client.

 

 

 

After downloading react in the client folder your directory structure will look something like this as shown below

 

 

 

Now we need to delete some files from this react client folder go to the src folder inside it delete the serviceWorker.js , logo.svg , index.css and app.test.js and after deleting those files you will get the following directory structure as shown below.

 

 

 

Now open index.js file and delete all the code which is auto generated by the react application for you and copy paste the below code

 

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

 

Now open the App.js file and delete all the code which is auto generated and copy paste the below code.

 

import React from 'react';
import './App.css';

const App = () =>  (
    <div className="App">
      app
    </div>
);

export default App;

 

Now another thing go to the package.json file which is located in the client folder. This is package.json file for react project. And add proxy : http://localhost:5000 line to it. Write at the bottom as shown below.

 

 

 

And very last one thing to do that is install the axios package in the client folder so that we can make requests in the front end application. Just go to command prmpt and cd into client and type this command shown below.

 

 

 

 

After installing axios in our client just make sure you enter the command cd .. to move to parent directory

 

 

And now we will running our both the servers i.e. express and react at the same time by running npm run dev command as shown below

 

 

 

Now if we open the url http://localhost:3000 we will see the react app something like this

 

 

Now if we open the url http://localhost:5000 we will see our express server something like this

 

 

 

As we can see there is a error there on express we have only configured the route for the following url /upload that is why when we open index route or home route is showing that error.

 

After this go to app.css and delete all the content inside it because we will be using bootstrap framework to style the application.

 

 

 

 

Now go to the index.html which is stored in the public folder and delete all the code which was generated by the react and copy paste the below code into it.

 

 

 

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"/>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="logo192.png" />
    
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  
    <title>React File Upload</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    
  </body>
  <!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</html>

 

In this code we are including the bootstrap css and jquery and bootstrap javascript also. Also we are importing the font awesome cdn for our react logo.

 

After this go to the App.js file and copy paste the below code to make the header of your application.

 

const App = () =>  (
    <div className="container">
      <h4 className="display-4 text-center mb-4">
        React File Upload
      </h4>

    </div>
);

 

READ  BootBoxJS - Bootstrap Modals Library For Creating Beautiful Bootstrap Modals

This is the simple heading which says React File Upload to it.

 

Now after that in the folder src create a new folder called as components and in that folder create a file called as fileupload.js as shown below.

 

 

 

This file will contain the code to actually upload the file to the server . This will be the image upload component of the application

 

import React , {Fragment} from 'react';

const FileUpload = () =>{
    return(
        <Fragment>
            <form>
            <div className="custom-file mb-4">
                <input type="file" className="custom-file-input" id="customFile"/>
                <label className="custom-file-label" htmlFor="customFile">Choose file</label>
            </div>
            <input type="submit" value="Upload" className="btn btn-primary btn-block mt-4"/>
            </form>
        </Fragment>
    );
};

export default FileUpload;

 

This image upload component contains the function of fileupload which basically returns this html which consists of a simple file upload form which has one input file where people can upload files and after that we have a button to actually submit the form and upload the file. And lastly we are exporting the component so that we can use in app.js

 

So move to app.js and import the component by writing the following line of code to it.

 

import FileUpload from './components/FileUpload';

 

And after importing the component we will actually use the component in the html. Just after the h4 heading ends just paste this line of code.

 

<FileUpload/>

 

So the full file looks like this

 

import React from 'react';
import FileUpload from './components/FileUpload';
import './App.css';

const App = () =>  (
    <div className="container">
      <h4 className="display-4 text-center mb-4">
        React File Upload
      </h4>
      <FileUpload/>

    </div>
);

export default App;

 

Now if we look into the browser we shall see something like below

 

 

So you can see above that we have a upload file form from which we can upload the files now.

 

Now we will create some state in your react application. We will create state in the application with the help of React Hooks. So first of all import the useState Hook to the fileupload.js

 

 

Now after importing the useState Hook . Now we will use it and set the state of both file and file name as follows:

 

 

 

We are defining two state variables for the actual file which needs to be uploaded and the file name. setFile and setFilename are methods which will set the state of the variable when it is changed. useState() function takes the default state value that needs to be attached. For file name the default value which will be shown to the user will be Choose File in the input form and whenever user chooses the file and it will be replaced by the actual file name.

 

Now we need to replace the Choose File label in the form with the state that we defined above. Just make the change as shown below.

 

 

 

After that we will bind the onchange event on the input field so that when we try to upload the file then this event will fire.

 

 

 

 

After declaring it now we will define the onChange function something like this

 

 

 

Now if we see the application again and upload any file to it we will see at the place of choose file the actual name of the file is being replaced as shown below.

 

 

 

Now after that we will bind the onSubmit event listener on the actual file upload form. Just do like this

 

 

 

After that we will define the onSubmit event listener like this

 

 

 

Now in this we are first of all preventing the default behavior of the form and then we are collecting for data by formData class and then we are appending the actual data to be uploaded by the key called as file because we have the file present in the path of the backend.

 

Now after this in order to make the request we will be importing the axios package in application like this

 

 

 

After this make the function onSubmit as async like this

 

 

 

After that just make another react hook for holding the response which will be getting from the backend. This will be uploadedFile. This is done like this

READ  Node.js API Authentication With JWT

 

 

 

Now we will be writing the post request to the actual url on the backend server express using the axios library and also setting the progress bar animation to the application . Just copy paste this code in this onsubmit function after you collected the form data.

 

try {
            const res = await axios.post('/upload', formData, {
              headers: {
                'Content-Type': 'multipart/form-data'
              }
            });
      
            const { fileName, filePath } = res.data;
      
            setUploadedFile({ fileName, filePath });
      
            
          } catch (err) {
            if (err.response.status === 500) {
              console.log("There was a problem with the server");
            } else {
              console.log(err.response.data.msg);
            }
          }

 

In this also we are printing any kind of error messages in the console so that we can see what is happening in the application.

 

Now if we run the application and try to upload the file we get a error like this no active directory is created

 

 

 

This error comes because the path that we are trying to upload the image in the backend includes this upload directory that we have not created. To fix this just create the upload directory and then the error will be fixed and we will be able to upload the image.

 

Just go to public folder and inside it create a new folder called as uploads like this

 

 

 

Now if we try to run the application again we will find that the new image being uploaded will be there in this uploads directory shown below

 

 

And when we try to look into the uploads directory we will be finding this xampp-control.exe file present like this

 

 

 

Now we need to display the image after the submit button of the upload form. Just go to below input submit button and copy paste this code shown below

 

{uploadedFile ? (
        <div className='row mt-5'>
          <div className='col-md-6 m-auto'>
            <h3 className='text-center'>{uploadedFile.fileName}</h3>
            <img style={{ width: '100%' }} src={uploadedFile.filePath} alt='' />
          </div>
        </div>
      ) : null}

 

Here we are using conditional statement when uploadedFile has some value then we are printing the file. We are using some bootstrap classes centering it and displaying the image name and also styling the image setting the width of image to 100%.

 

 

 

Now we will be setting some messages such as image is uploaded or there is some kind of error such as 400 or 500 server error. For these messages let me create a react hook something like this

 

const [message,setMessage] = useState('');

 

Now just replace console.log with setMessage like this

 

 

 

For this setMessage to work we need to create another component Message.js inside components folder like this

 

 

And copy paste the followind code into the Messages.js file

 

import React from 'react';
import PropTypes from 'prop-types';

const Message = ({ msg }) => {
  return (
    <div className='alert alert-info alert-dismissible fade show' role='alert'>
      {msg}
      <button
        type='button'
        className='close'
        data-dismiss='alert'
        aria-label='Close'
      >
        <span aria-hidden='true'>×</span>
      </button>
    </div>
  );
};

Message.propTypes = {
  msg: PropTypes.string.isRequired
};

export default Message;

 

In this File we are using the bootstrap alert classes to make the alert boxes appear beautiful. If you open the application now you will see the erros like this in a beautiful alert box.

 

After that we will add progress bar to the application like this. First of all create a react hook for that like this

 

const [uploadPercentage, setUploadPercentage] = useState(0);

 

onUploadProgress: progressEvent => {
          setUploadPercentage(
            parseInt(
              Math.round((progressEvent.loaded * 100) / progressEvent.total)
            )
          );

          // Clear percentage
          setTimeout(() => setUploadPercentage(0), 10000);
        }
      });

 

Create a new Progress.js Component in the components folder like this

 

import React from 'react';
import PropTypes from 'prop-types';

const Progress = ({ percentage }) => {
  return (
    <div className='progress'>
      <div
        className='progress-bar progress-bar-striped bg-success'
        role='progressbar'
        style={{ width: `${percentage}%` }}
      >
        {percentage}%
      </div>
    </div>
  );
};

Progress.propTypes = {
  percentage: PropTypes.number.isRequired
};

export default Progress;

 

We can now use this component in our application like this

 

import Progress from './Progress';

 

<Progress percentage={uploadPercentage} />

 

Now if you open the application you will find the progress bar also attached with the application when we try to upload the file like this

 

 

 

 

Now the Application is complete guys thanks very much for reading this post. All the source code is available to download below.  Click it to download the zip file

 

 

 

Download Source Code

Leave a Reply

Close Menu