2015-02-26 4 views
58

Я искал повсюду какую-то помощь в создании компонента, помогающего управлять загрузкой файлов изнутри Реагировать на конечную точку, которую у меня установлена.Загрузить файл Компонент с ReactJS

Я пробовал множество опций, включая интеграцию http://filedropjs.org. Я решил против него, потому что у меня нет контроля над элементами, которые он устанавливает в DOM с new FileDrop('zone', options);

Это то, что я до сих пор:

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> 
     ); 
    } 
} 
}); 

Если кто-то может просто указать мне в В правильном направлении я бы послал несколько виртуальных объятий. Я работаю над этим довольно широко. Я чувствую, что я рядом, но не совсем там.

Спасибо!

+0

Не уверен, что если вы можете использовать это или нет - возможно, нет - но только в том case: http://hayageek.com/docs/jquery-upload-file.php – gibberish

+0

как насчет чего-то такого простого, как этот http://jsbin.com/qulozo/2? – Dhiraj

+0

Я собрал простой пост в блоге, в котором излагаются простые шаги для загрузки изображения с использованием React с Node.js, а также загрузка на S3: http://www.benrlodge.com/blog/post/image-uploading-with- reactjs-nodejs-and-aws-s3 – Ben

ответ

66

Я работал над этим довольно долгое время, а также. Это то, что я придумал.

A Dropzone Компонент, в сочетании с использованием 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 

Использование Dropzone.

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

Когда файл добавляется в зону перетаскивания, добавьте его в список загружаемых файлов. Я добавляю его в свой магазин флюсов.

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); 
    } 

Вы можете использовать imageUrl для отображения предварительного просмотра файла.

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

Чтобы загрузить файлы, получить список файлов и отправить их через суперагент. Я использую флюс, поэтому получаю список изображений из этого магазина.

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'); 
     }); 
    } 
+0

Что такое 'this.executeAction (newImageAction, newFile);' делать? Не следует ли заменить newImageAction чем-то? Кроме того, где должен состоять конечный блок кода - в компоненте Dropzone или в магазине? – frogbandit

+0

@frogbandit 'this.executeAction()' из флюксибельной системы Yahoo. http://fluxible.io - какой последний кодовый блок вы имеете в виду? –

+0

@JoeMcBride Gotcha. Что он должен делать? Это всегда дает мне 'newImageAction не определен' – frogbandit

28

Это может помочь

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> 
     ); 
    } 
}); 

заимствован отсюда How to send FormData objects with Ajax-requests in jQuery?

+2

Это ужасно! Хорошо работает во всех браузерах, о которых я мог думать. Благодаря! –

+2

Начиная с React 0.14 "this.refs.file" * является * узлом DOM, поэтому getDOMNode устарел. Линия fd.append становится: fd.append('file', this.refs.file.files[0]); jomofrodo

2

я столкнулся с задачей получения, что facebook или Gmail, как поведение, где ваша цель падения подчеркивает, как только пользователь начинает перетаскивание файла в любом месте над окном. Не было готового решения для перетаскивания, которое я мог найти. Итак, я сделал это.

Он предназначен для того, чтобы быть голыми костями, снабжая вас базой для настройки и стиля, как ваш собственный. Он предоставляет много крючков, чтобы вы могли это сделать. Но есть также демонстрация, которая дает вам пример, чтобы уйти.

Проверьте это: https://www.npmjs.com/package/react-file-drop

Демо: http://sarink.github.io/react-file-drop/demo/

+0

Я не могу получить эту работу: https://jsfiddle.net/westhomas/rr1xbapc/7/ – wes

+0

Как ваш код отличается от моей рабочей демонстрации? – sarink

+0

@KabirSarin response-file-drop имеет функцию удаления файла? –

2

Существует Dropzone НПМ пакет для этого https://www.npmjs.com/package/react-dropzone

+0

http://okonet.ru/react-dropzone/ принимает только изображения? Мне нужно перетащить файл с заданным типом. Является ли это возможным ? –