Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload File Component with ReactJS

I've been looking everywhere for some help on making a component to help manage uploading files from within React to an endpoint I have setup.

I've tried numerous options, including integrating filedropjs. I decided against it because I don't have control over the elements it sets up in the DOM with the new FileDrop('zone', options);

This is what I have so far:

module.exports =  React.createClass({ displayName: "Upload", handleChange: function(e){      formData = this.refs.uploadForm.getDOMNode();      jQuery.ajax({         url: 'http://example.com',         type : 'POST',         xhr: function(){             var myXhr = $.ajaxSettings.xhr();             if(myXhr.upload){                 myXhr.upload.addEventListener('progress',progressHandlingFunction, false);             }             return myXhr;         },         data: formData,         cache: false,         contentType: false,         processData: false,         success: function(data){             alert(data);         }     });  }, render: function(){          return (             <form ref="uploadForm" className="uploader" encType="multipart/form-data" onChange={this.handleChange}>                 <input ref="file" type="file" name="file" className="upload-file"/>             </form>         );    }   });    }, render: function(){      console.log(this.props.content);      if(this.props.content != ""){         return (             <img src={this.props.content} />         );     } else {         return (             <form className="uploader" encType="multipart/form-data" onChange={this.handleChange}>                 <input ref="file" type="file" name="file" className="upload-file"/>             </form>         );     } } }); 

If someone could just point me in the right direction I would send some virtual hugs. I've been working on this quite extensively. I feel like I'm close, but not quite there.

Thanks!

like image 364
Dan Avatar asked Feb 26 '15 18:02

Dan


People also ask

How do I upload a file using react JS?

In order to upload files, the 'content-type' header must be set to 'multipart/form-data'. new FormData() creates a new empty formData object that we send as the payload in our POST request. Our POST request assumes there is an API endpoint on our backend server at http://localhost:3000/uploadFile. We're done!

How do I upload a PDF to Reactjs?

Install by executing npm install react-pdf or yarn add react-pdf . Import by adding import { Document } from 'react-pdf' . Use by adding <Document file="..." /> . file can be a URL, base64 content, Uint8Array, and more.


2 Answers

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 &amp; 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');         });     } 
like image 140
Joe McBride Avatar answered Oct 13 '22 18:10

Joe McBride


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?

like image 37
mike123 Avatar answered Oct 13 '22 19:10

mike123