Upload File Component with ReactJS Upload File Component with ReactJS ajax ajax

Upload File Component with ReactJS


I worked on this quite a while as well. This what I came up with.

A Dropzone component, coupled with using superagent.

// based on https://github.com/paramaggarwal/react-dropzone, adds image preview    const React = require('react');const _ = require('lodash');var Dropzone = React.createClass({  getInitialState: function() {    return {      isDragActive: false    }  },  propTypes: {    onDrop: React.PropTypes.func.isRequired,    size: React.PropTypes.number,    style: React.PropTypes.object  },  onDragLeave: function(e) {    this.setState({      isDragActive: false    });  },  onDragOver: function(e) {    e.preventDefault();    e.dataTransfer.dropEffect = 'copy';    this.setState({      isDragActive: true    });  },  onDrop: function(e) {    e.preventDefault();    this.setState({      isDragActive: false    });    var files;    if (e.dataTransfer) {      files = e.dataTransfer.files;    } else if (e.target) {      files = e.target.files;    }    _.each(files, this._createPreview);  },  onClick: function () {    this.refs.fileInput.getDOMNode().click();  },  _createPreview: function(file){    var self = this      , newFile      , reader = new FileReader();    reader.onloadend = function(e){      newFile = {file:file, imageUrl:e.target.result};      if (self.props.onDrop) {        self.props.onDrop(newFile);      }    };    reader.readAsDataURL(file);  },  render: function() {    var className = 'dropzone';    if (this.state.isDragActive) {      className += ' active';    };    var style = {      width: this.props.size || 100,      height: this.props.size || 100,      borderStyle: this.state.isDragActive ? 'solid' : 'dashed'    };    return (      <div className={className} onClick={this.onClick} onDragLeave={this.onDragLeave} onDragOver={this.onDragOver} onDrop={this.onDrop}>        <input style={{display: 'none' }} type='file' multiple ref='fileInput' onChange={this.onDrop} />        {this.props.children}      </div>    );  }});module.exports = Dropzone

Using the Dropzone.

    <Dropzone onDrop={this.onAddFile}>      <p>Drag & drop files here or click here to browse for files.</p>    </Dropzone>

When a file is added to the drop zone, add it to your list of files to upload. I add it to my flux store.

  onAddFile: function(res){    var newFile = {      id:uuid(),      name:res.file.name,      size: res.file.size,      altText:'',      caption: '',      file:res.file,      url:res.imageUrl    };    this.executeAction(newImageAction, newFile);  }

You can use the imageUrl to display a preview of the file.

  <img ref="img" src={this.state.imageUrl} width="120" height="120"/>

To upload the files, get the list of files and send them through superagent. I'm using flux, so I get the list of images from that store.

  request = require('superagent-bluebird-promise')  Promise = require('bluebird')    upload: function(){      var images = this.getStore(ProductsStore).getNewImages();      var csrf = this.getStore(ApplicationStore).token;      var url = '/images/upload';      var requests = [];      var promise;      var self = this;      _.each(images, function(img){        if(!img.name || img.name.length == 0) return;        promise = request          .post(url)          .field('name', img.name)          .field('altText', img.altText)          .field('caption', img.caption)          .field('size', img.size)          .attach('image', img.file, img.file.name)          .set('Accept', 'application/json')          .set('x-csrf-token', csrf)          .on('progress', function(e) {            console.log('Percentage done: ', e.percent);          })          .promise()          .then(function(res){            var newImg = res.body.result;            newImg.id = img.id;            self.executeAction(savedNewImageAction, newImg);          })          .catch(function(err){            self.executeAction(savedNewImageErrorAction, err.res.body.errors);          });        requests.push(promise);      });      Promise        .all(requests)        .then(function(){          console.log('all done');        })        .catch(function(){          console.log('done with errors');        });    }


This may help

var FormUpload = React.createClass({    uploadFile: function (e) {        var fd = new FormData();            fd.append('file', this.refs.file.getDOMNode().files[0]);        $.ajax({            url: 'http://localhost:51218/api/Values/UploadFile',            data: fd,            processData: false,            contentType: false,            type: 'POST',            success: function(data){                alert(data);            }         });        e.preventDefault()    },    render: function() {        return (            <div>                               <form ref="uploadForm" className="uploader" encType="multipart/form-data" >                   <input ref="file" type="file" name="file" className="upload-file"/>                   <input type="button" ref="button" value="Upload" onClick={this.uploadFile} />               </form>                            </div>        );    }});

borrowed from here How to send FormData objects with Ajax-requests in jQuery?


I was faced with the task of getting that facebook or gmail-like behavior where your drop target highlights as soon as the user begins dragging a file anywhere over the window. There was no off-the-shelf React drag and drop solution that I could find. So, I made one.

It is meant to be bare-bones, supplying you with a base to customize and style as your own. It provides many hooks to enable you to do this. But there is also a demo that gives you an example to go off of.

Check it out: https://www.npmjs.com/package/react-file-drop

Demo: http://sarink.github.io/react-file-drop/demo/