Handling file upload in reactjs

Saurabh Mhatre
CodeClassifiers
Published in
4 min readMar 7, 2017

In many real world scenarios we require various types of files to be uploaded from user. In today’s tutorial we are going to cover basic file upload using reactjs.

So let’s get started:

We are going to make changes in the uploadScreen component that we created in the login tutorial here.We are going to need react-dropzone and material-ui npm modules for handling file upload and designing app ui.Install them by running the following command in your project:

npm install --save react-dropzone material-ui

Now let’s get back to editing uploadScreen.js:

import Dropzone from 'react-dropzone';
....
class UploadScreen extends Component {
render() {
return (
<div className="App">
<Dropzone onDrop={(files) => this.onDrop(files)}>
<div>Try dropping some files here, or click to select files to upload.</div>
</Dropzone>
</div>
)
}
}

This will create basic dropzone for selecting files from directories.Next we create onDrop handler to temporarily save selected files:

class UploadScreen extends Component {
constructor(props){
super(props);
this.state={
filesToBeSent:[],
}
}
onDrop(acceptedFiles, rejectedFiles) {
// console.log('Accepted files: ', acceptedFiles[0].name);
var filesToBeSent=this.state.filesToBeSent;
filesToBeSent.push(acceptedFiles);
this.setState({filesToBeSent});
}
...
}

This will allow users to select multiple files before uploading them. Next we will create a filesPreview div where all of user selected files will be displayed until the user is ready to upload files:

import React, { Component } from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Dropzone from 'react-dropzone';
import FontIcon from 'material-ui/FontIcon';
import {blue500, red500, greenA200} from 'material-ui/styles/colors';
class UploadScreen extends Component {
constructor(props){
super(props);
this.state={
filesPreview:[],
filesToBeSent:[],
printcount:10,
}
}
onDrop(acceptedFiles, rejectedFiles) {
// console.log('Accepted files: ', acceptedFiles[0].name);
var filesToBeSent=this.state.filesToBeSent;
if(filesToBeSent.length < this.state.printcount){
filesToBeSent.push(acceptedFiles);
var filesPreview=[];
for(var i in filesToBeSent){
filesPreview.push(<div>
{filesToBeSent[i][0].name}
<MuiThemeProvider>
<a href="#"><FontIcon
className="material-icons customstyle"
color={blue500}
styles={{ top:10,}}
>clear</FontIcon></a>
</MuiThemeProvider>
</div>
)
}
this.setState({filesToBeSent,filesPreview});
}
else{
alert("You have reached the limit of printing files at a time")
}
}
render() {
return (
<div className="App">
<Dropzone onDrop={(files) => this.onDrop(files)}>
<div>Try dropping some files here, or click to select files to upload.</div>
</Dropzone>
<div>
Files to be printed are:
{this.state.filesPreview}
</div>
</div>
)
}
}

Here we have set max file selection count to 10 which can be adjusted based on your needs.On every file selection onDrop function takes previously selected files as input,appends newly selected file and updates filePreview div to display files.

Next we are going to make UI a little better and add an upload button to send files to server once user has selected all the files:

class UploadScreen extends Component {
...
render() {
return (
<div className="App">
<MuiThemeProvider>
<div>
<AppBar
title="Print Files"
/>
</div>
</MuiThemeProvider>
<center>
<div>
You can upload upto {this.state.printcount} files at a time.
</div>
<Dropzone onDrop={(files) => this.onDrop(files)}>
<div>Try dropping some files here, or click to select files to upload.</div>
</Dropzone>
<div>
Files to be printed are:
{this.state.filesPreview}
</div>
</center>
<div>
{this.state.printingmessage}
</div>
<MuiThemeProvider>
<RaisedButton label="Print Files" primary={true} style={style} onClick={(event) => this.handleClick(event)}/>
</MuiThemeProvider>
</div>
</div>
);
}
}
const style = {
margin: 15,
};
export default UploadScreen;

As you can see we need to implement handleClick in the onClick handler in which we will upload files to server.We are going to use superagent module to upload files to server which can be installed by running the following command:

npm install --save superagent

The handleClick function is implemented as follows:

/*
Module:superagent
superagent is used to handle post/get requests to server
*/
var request = require('superagent');
var apiBaseUrl = "http://localhost:4000/api/";
class UploadScreen extends Component {
....
handleClick(event){
// console.log("handleClick",event);
var self = this;
if(this.state.filesToBeSent.length>0){
var filesArray = this.state.filesToBeSent;
var req = request.post(apiBaseUrl+'fileupload');
for(var i in filesArray){
// console.log("files",filesArray[i][0]);
req.attach(filesArray[i][0].name,filesArray[i][0])
}
req.end(function(err,res){
if(err){
console.log("error ocurred");
}
console.log("res",res);
alert("File printing completed")
});
}
else{
alert("Please upload some files first");
}
}
...
}

In the handleClick function we first check if user has selected any files,then we store fileToBeSent in a local variable fileArray and attach each file with name to req variable responsible for sending request to backend. I have created backend apis in nodejs which I will be covering in next tutorial.For now just assume that there is a fileupload route running on port 4000 on localhost which will accept files from frontend in a post request.

Here is a screenshot of the final app screen:

fileuploadscreenshot

The user is greeted with alert that file have finished uploading once we receive a response from backend apis. That finishes off our today’s tutorial. Check out some bonus tips and you can see the complete code at end of bonus tips.

Bonus Tips:

1)We can keep the submit button disabled when user clicks it until we finish file uploading to server in order to prevent multiple upload requests to server.You can also add loading spinner or uploading message until uploading is finished.

2)Material UI supports in app drawer which can be modified further to add more features like upload history and user management.

There are many additions that can be done to the code which I have covered in the bonus tips sections and covered some of them in complete code uploaded on github gist here.

In case you need to develop backend apis in nodejs for handling filee upload in the backend then you can find the tutorial here.

Connect Deeper:

Follow our facebook page to get notified about next tutorial in the series in which I will cover retrieving files uploaded in the past by the user here: Technoetics or simply follow our publication on medium.

--

--

Saurabh Mhatre
CodeClassifiers

Senior Frontend Developer with 9+ years industry experience. Content creator on Youtube and Medium. LinkedIn/Twitter/Instagram: @SaurabhNative