Компонент загрузки файла с ReactJS

58

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

Я пробовал множество опций, включая интеграцию 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
    Не уверен, что вы можете использовать это или нет - возможно, нет - но на всякий случай: hayageek.com/docs/jquery-upload-file.php
  • 0
    как насчет чего-то такого простого, как этот jsbin.com/qulozo/2 ?
Показать ещё 2 комментария
Теги:

4 ответа

69
Лучший ответ

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

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 или в Магазине?
  • 0
    @frogbandit this.executeAction() из среды Fluxible от Yahoo. fluxible.io - какой последний кодовый блок вы имеете в виду?
Показать ещё 4 комментария
26

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

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

заимствован отсюда Как отправить объекты FormData с помощью Ajax-запросов в jQuery?

  • 2
    Это здорово! Прекрасно работает во всех браузерах, о которых я только мог подумать. Спасибо!
  • 4
    Начиная с версии 0.14 «this.refs.file» является узлом DOM, поэтому getDOMNode устарела. Строка fd.append становится следующей: <code> fd.append ('file', this.refs.file.files [0]); </ code>
2

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

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

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

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

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

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

  • 0
    Я не могу заставить это работать: jsfiddle.net/westhomas/rr1xbapc/7
  • 0
    Чем ваш код отличается от моей рабочей демонстрации?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню