React.js

ReactJS File Upload Example

In this article we build a File Upload Feature using ReactJS. ReactJS has gained ground and has become the go to library for Front end Development. We take a look at how to build a feature to upload files in a ReactJS Application. We will use the ubiquitous XMLHttpRequest Object to post the file data to the server. Also, we will build a simple Server side API to accept the uploaded file. To make things interesting we also provide a progress indicator.

So, without further ado let us get started.

Firstly let me list out the tools and technologies used in this article.

1. Tools and Technologies

  • create-react-app CLI tool
  • Node.js
  • Formidable package
  • Concurrently package
  • Visual Studio Code IDE

create-react-app is a command line tool from the folks who created React. This tool allows us to quickly generate the skeletal or structure upon which we can build a full blown ReactJS Application. We use it here to create the starting point of our example. We use Node.js to build a simple API which allows us to post the file we want to upload. Node.js is basically JavaScript on the server side. The formidable npm package allows us to parse and save the uploaded file. Concurrently package will allow us to launch both our client side as well as server side code simultaneously.

Visual Studio Code IDE is my favorite IDE for JavaScript development. But feel free to use a different editor if you need to.

2. Application Structure

First we generate our client side ReactJS application structure by executing the below command:

>npx create-react-app my-app

This command generated the following folder structure of our application.

ReactJS File Upload - Project Structure
Project Structure

Now let us setup our Server side API project structure. Firstly let us create a folder named api and place a single file under it named index.js. Then let us install our dependency viz., Formidable by running the below command:

/api>npm i formidable

This will install our dependency and also save it in the newly created package.json file. Now the structure of our server side project should look like below:

Project Structure

We are not set and good to go with both our client side and server side application structure set up. Next let us start working on our client side application.

3. Client Side Application

We will write two components to achieve the File uploading functionality. One would be a ProgressBar component that takes as its props the percentage of completion. Second the FileUpload component that renders an input tag of type file. We hide this input and instead show a button. On the click of this button we simulate a click on the file input. This in turn triggers the select file dialog. Once the user selects file(s) we process them and post them to our server side API. The code for our simple Progress Bar component looks like below:

ProgressBar.js

import React from 'react';

function ProgressBar(props) {
    return <div 
style={{ height: '7px', 
         width: '220px', 
         backgroundColor: 'whitesmoke' }}>
        <div 
style={{ 
         height: '100%', 
         width: props.progress, 
         backgroundColor: 'blue' }}></div>
    </div>;
}

export default ProgressBar;

The code for our main FileUpload component looks like below:

FileUpload.js

import React, { useState, createRef } from 'react';
import ProgressBar from './ProgressBar';

function FileUploader(props) {
    const [progress, setProgress] = useState("0%");
    let files = [];
    const fileInput = createRef();
    const processFiles = () => {
        var request = new XMLHttpRequest();
        setProgress("0%");
        files = fileInput.current.files;
        if (files.length === 0) return;
        request.upload.addEventListener("progress", showProgress);
        request.open("POST", "/uploadFile", true);
        var formData = new FormData();
        for (var file = 0; file < files.length; file++) {

            formData.append("file" + file, 
                            files[file], files[file].name);

        }
        request.send(formData);
    }
    const showProgress = (evt) => {
        let percentage = (((evt.loaded / evt.total) * 100)) + "%";
        setProgress(percentage);
    }
    return <>
        <input type="file" multiple={true} id='browser' 
            style={{ display: 'none' }} ref={fileInput} 
            onChange={processFiles} />
        <button 
onClick={() => { document.getElementById('browser').click();}}>
             Browse</button>
        <ProgressBar progress={progress} />
        {progress === "100%" && 
             <span>File Uploaded Successfully!</span>}
    </>

}

export default FileUploader;

Now let us turn our attention to the server side code.

4. Server Side API

We use the http module in Nodejs to create a basic API. We accept POST request, The API expects the request body to have files that are to be uploaded. The API places the files in the "c:/data/" folder. The code for our API looks like below:

index.js

var http = require("http");
var url = require("url");
var fs = require("fs");
var formidable = require("formidable");
var port = 8090;
var host = "localhost";

http.createServer(function (req, res) {
    var path = url.parse(req.url, true);
    if (path.pathname.endsWith("uploadFile")) {
        var form = new formidable.IncomingForm();

        form.parse(req, function (err, fields, files) {

            for (var file in files) {
                if (!files.hasOwnProperty(file)) continue;
                var oldpath = files[file].path;
                var newpath = `C:/data/${files[file].name}`;
                fs.renameSync(oldpath, newpath);
            }
            res.write('File uploaded and moved!');
            res.end();
        });

    }

}).listen(port, host);

5. Running the Application

To run this application, we need to perform a couple of steps. First we need concurrently, we install it to the root of our application like below:

/>npm i concurrently

Our completed project structure with both server side and client side code should now look like below:

ReactJS File Upload - Project Structure
Project Structure

Now we need to add a command to the root package.json to launch both the API and client side code. Our root package.json file should look like below:

package.json

{
  "name": "react-js-file-upload-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "concurrently \"npm start --prefix 
my-app/\" \"npm start --prefix api/\"",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Siddharth Seth",
  "license": "ISC",
  "dependencies": {
    "concurrently": "^5.2.0"
  }
}

Let us now run our application, using the command below:

>npm start

The output should look like below:

ReactJS File Upload - Project Output
Project Output
Project Output

This wraps up our look at File Upload using ReactJS Example. To get the code for this example check out the section below:

6. Download the Source Code

Download
You can download the full source code of this example here: ReactJS File Upload Example

Siddharth Seth

Siddharth is a Software Development Professional with a Master degree in Computer Applications from IGNOU. He has over 14 years of experience. And currently focused on Software Architecture, Cloud Computing, JavaScript Frameworks for Client and Server, Business Intelligence.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button