En este post se explica como se podría capturar una imagen con react, para posteriormente poder realizar con ella las acciones requeridas.

Para ello empezaremos creándonos dos Componentes React:

1. FileUploader

export default class FileUploader extends Component {
 

  render() {
    let state = this.state,
      props = this.props;
    return (
      <form name="form" id="form">
      </form>
    );
  }
}

FileUploader.propTypes = propTypes;
FileUploader.defaultProps = defaultProps;

2.Imágenes:

import React, { Component } from "react";
import FileUploader from "./FileUploader";
import axios from "axios";
export default class Imagenes extends Component {
  uploader = React.createRef();
  render() {
    return (
      <div>
        <FileUploader ref={this.uploader} />
        <button type="submit">
          Enviar
        </button>
      </div>
    );
  }
}

Como podemos comprobar FileReader lo usaremos dentro de imágenes.js. FileReader contendrá el formulario del que posteriormente será utilizado para recoger la imagen

<form name="form" ref={this.formRef} id="form">
        <label
          onDragEnter={this.onDragEnter}
          onDragLeave={this.onDragLeave}
          onDragOver={this.onDragOver}
          onDrop={this.onDrop}
        >
          <img src={state.imageSrc} />
          <i className="icon icon-upload"></i>
          <input
            type="file"
            accept="image/*"
            onChange={this.onFileChange}
            ref="input"
          />
        </label>
      </form>

Añadimos el constructor de FileReader:

constructor(props) {
    super(props);

    this.state = {
      active: false,
      imageSrc: "",
      imageName: "",
      image: [],
      loaded: false
    };

    this.onDragEnter = this.onDragEnter.bind(this);
    this.onDragLeave = this.onDragLeave.bind(this);
    this.onDrop = this.onDrop.bind(this);
    this.onFileChange = this.onFileChange.bind(this);
  }

Creamos dentro del FileReader los métodos que serán llamados según el evento:

onDragEnter(e) {
    this.setState({ active: true });
  }

  onDragLeave(e) {
    this.setState({ active: false });
  }

  onDragOver(e) {
    e.preventDefault();
  }

  onDrop(e) {
    e.preventDefault();
    this.setState({ active: false });
    this.onFileChange(e, e.dataTransfer.files[0]);
  }
  onFileChange(e, file) {
    console.log("on-file-change");
    var file = file || e.target.files[0],
      pattern = /image-*/,
      reader = new FileReader();
    console.log(file.name);
    if (!file.type.match(pattern)) {
      alert("Formato inválido");
      return;
    }
    console.log(this);
    this.setState({ loaded: false });

    reader.onload = e => {
      this.setState({
        imageSrc: reader.result,
        loaded: true,
        imageName: file.name
      });
      console.log(reader.result);
    };
    reader.readAsDataURL(file);
  }

Y lo ultimo aquí seria añadir dentro de FileReader métodos por el cual leeremos características de lo que hemos seleccionado en el formulario:

getFileName() {
    return this.state.imageName;
  }
  getFileObject() {
    return this.refs.input.files[0];
  }

  getFileString() {
    return this.state.imageSrc;
  }

FileReader debería quedar asi:

import React, { Component } from "react";

export default class FileUploader extends Component {
  form = React.createRef();
  state = {
    active: false,
    imageSrc: "",
    imageName: "",
    image: [],
    loaded: false
  };
  constructor(props) {
    super(props);

    this.state = {
      active: false,
      imageSrc: "",
      imageName: "",
      image: [],
      loaded: false
    };

    this.onDragEnter = this.onDragEnter.bind(this);
    this.onDragLeave = this.onDragLeave.bind(this);
    this.onDrop = this.onDrop.bind(this);
    this.onFileChange = this.onFileChange.bind(this);
  }

  onDragEnter(e) {
    this.setState({ active: true });
  }

  onDragLeave(e) {
    this.setState({ active: false });
  }

  onDragOver(e) {
    e.preventDefault();
  }

  onDrop(e) {
    e.preventDefault();
    this.setState({ active: false });
    this.onFileChange(e, e.dataTransfer.files[0]);
  }

  onFileChange(e, file) {
    console.log("on-file-change");
    var file = file || e.target.files[0],
      pattern = /image-*/,
      reader = new FileReader();
    console.log(file.name);
    if (!file.type.match(pattern)) {
      alert("Formato inválido");
      return;
    }
    console.log(this);
    this.setState({ loaded: false });

    reader.onload = e => {
      this.setState({
        imageSrc: reader.result,
        loaded: true,
        imageName: file.name
      });
      console.log(reader.result);
    };
    reader.readAsDataURL(file);
  }

  getFileName() {
    return this.state.imageName;
  }
  getFileObject() {
    return this.refs.input.files[0];
  }

  getFileString() {
    return this.state.imageSrc;
  }

  render() {
    let state = this.state,
      props = this.props;
    return (
      <form name="form" ref={this.formRef} id="form">
        <label
          onDragEnter={this.onDragEnter}
          onDragLeave={this.onDragLeave}
          onDragOver={this.onDragOver}
          onDrop={this.onDrop}
        >
          <img src={state.imageSrc} />
          <i className="icon icon-upload"></i>
          <input
            type="file"
            accept="image/*"
            onChange={this.onFileChange}
            ref="input"
          />
        </label>
      </form>
    );
  }
}

Por consiguiente se trabajara sobre imagenes.js, que contiene FileReader y se dedica a realizar las acciones que queramos con lo que nos ofrece este FileReader.

Incluimos dentro del render FileReader:

render() {
    return (
      <div>
        <FileUploader ref={this.uploader} />
        <button type="submit" onClick={this.onClick}>
          Enviar
        </button>
      </div>
    );
  }

Indicamos el constuctor y la referencia a FileReader de imagenes:

uploader = React.createRef();
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
  }

Por ultimo añadimos las acciones que se requieran para la trata del fichero

onClick(e) {
    e.preventDefault();

    var url =
        "https://apiempleadosier.azurewebsites.net/api/Prueba/InsertarPrueba",
      formData = new FormData(document.getElementById("form"));
    var urlimagen =
      "https://apiempleadosier.azurewebsites.net/Imagen/SubirImagen";
    console.log(this.uploader.current);
    if (undefined === this.uploader.current) return;

    formData.append("file", this.uploader.current.getFileObject());
    var json = {
      idPrueba: 4,
      imagen: this.uploader.current.getFileName(),
      texto: "Hola que tal"
    };
    var jsonimagen = { imagenRaw: this.uploader.current.getFileObject() };

    axios.post(url, json).then(console.log("Guay"));
    //axios
    //.post(urlimagen, this.uploader.current.getFileObject())
    //.then(console.log("Guayx2"));
  }

Yo he utilizado un servicio de azure en que se puede hacer post con un objeto, que en el api he denominado como prueba y tiene tres campos, idPrueba, imagen y texto.

El campo imagen recoge el nombre del fichero que FileReader ha recogido.

imágenes.js debe quedar de esta forma:

import React, { Component } from "react";
import FileUploader from "./FileUploader";
import axios from "axios";
export default class Imagenes extends Component {
  uploader = React.createRef();
  constructor(props) {
    super(props);
    this.onClick = this.onClick.bind(this);
  }

  onClick(e) {
    e.preventDefault();

    var url =
        "https://apiempleadosier.azurewebsites.net/api/Prueba/InsertarPrueba",
      formData = new FormData(document.getElementById("form"));
    var urlimagen =
      "https://apiempleadosier.azurewebsites.net/Imagen/SubirImagen";
    console.log(this.uploader.current);
    if (undefined === this.uploader.current) return;

    formData.append("file", this.uploader.current.getFileObject());
    var json = {
      idPrueba: 4,
      imagen: this.uploader.current.getFileName(),
      texto: "Hola que tal"
    };
    var jsonimagen = { imagenRaw: this.uploader.current.getFileObject() };

    axios.post(url, json).then(console.log("Guay"));
    //axios
    //.post(urlimagen, this.uploader.current.getFileObject())
    //.then(console.log("Guayx2"));
  }

  render() {
    return (
      <div>
        <FileUploader ref={this.uploader} />
        <button type="submit" onClick={this.onClick}>
          Enviar
        </button>
      </div>
    );
  }
}

Y bueno esto seria todo, con esto podríamos subir imágenes con React, con Drag&Drop.

Muchas gracias por leer mi post sobre esta tecnología, para mi ha sido un placer ofrecer este conocimiento.

Autor/a: Iván Encinas Rodríguez

Curso: Microsoft MCSA Web Applications + Microsoft MCSD App Builder + Xamarin

Centro: Tajamar

Año académico: 2019-2020

Código / recursos utilizados / Otros datos de interés: https://github.com/SuperBash/ImagenesReact

Leave a Comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.