No puede prever múltiples archivos de carga en forma

En un formulario multiparto, puedo previsualizar una sola imagen de carga usando:

 function readURL(input) {
      if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function (e) {
          let image = new Image();
          image.src = `${e.target.result}`;
          image.className = "img-thumbnail"
          let closeBtn = ``;
          let wrapper = $('
'); $('#images-to-upload').append(wrapper); $(wrapper).append(image); $(wrapper).append(closeBtn); } reader.readAsDataURL(input.files[0]); } } $("#imgInput").change(function () { readURL(this); });

Pero me gustaría prever TODAS las imágenes subidas, así que hice este ajuste al código anterior agregando un bucle:

function readURL(input) {
  if (input.files && input.files[0]) {
    let files = input.files;
    
    for (var i = 0; i < input.files.length; i++) {
      var reader = new FileReader();
      reader.onload = function (e) {
        let image = new Image();
        image.src = `${e.target.result[i]}`;
        image.className = "img-thumbnail"
        let closeBtn = ``;
        let wrapper = $('
'); $('#images-to-upload').append(wrapper); $(wrapper).append(image); $(wrapper).append(closeBtn); } }; reader.readAsDataURL(input.files[i]); // error here } }

Pero ahora tengo este error:

143 Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'

¿Cómo puedo arreglar esto?

Pregunta hecha hace 3 años, 5 meses, 0 días - Por codemasterx


3 Respuestas:

  • Es porque el reader.readAsDataURL(input.files[i]); está fuera del bucle. Pero así no es como lo haces. El FileReader puede procesar sólo un archivo en ese momento. Esto significa que tienes que crear una instancia de la FileReader para cada imagen en la entrada.

    Sugiero dividirlo en 2 funciones de legibilidad.

    
    function previewImage(file) {
      const reader = new FileReader();
      reader.onload = function (e) {
        let image = new Image();
        image.src = e.target.result;
        image.className = "img-thumbnail";
        let closeBtn = ``;
        let wrapper = $('
    '); $("#images-to-upload").append(wrapper); $(wrapper).append(image); $(wrapper).append(closeBtn); }; reader.readAsDataURL(file); } function readURL(input) { if (input.files.length) { Array.from(input.files).forEach((file) => previewImage(file)); } }

    Hice algunos cambios:

    • if (input.files.length) { - la entrada de archivo siempre tiene archivos FileList objeto así que no hay necesidad de comprobar si existe, y sólo comprobar si tiene una longitud, que significa al menos un archivo está presente
    • Array.from(input.files) - transformaciones FileList en un array ordinario fo puede utilizar funciones de array, como forEach

    El resto es igual. In image.src = e.target.result;, no hay necesidad de hacerlo cuerda ya que es una cuerda. También el resultado establecido en el FileReader clase no puede ser array.

    Respondida el Dec 17, 2020 a las 20:05 - por syntaxsniper

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás experimentando se debe a que estás intentando acceder a input.files[i] dentro de la función readURL antes de que el FileReader sea inicializado y también estás pasando incorrectamente el parámetro en reader.readAsDataURL(input.files[i]);.

    Para solucionar este problema, puedes modificar tu función readURL de la siguiente manera:

    ```javascript function readURL(input) { if (input.files && input.files.length > 0) { let files = input.files;

    for (var i = 0; i < files.length; i++) {
      var reader = new FileReader();
    
      reader.onload = (function (file) {
        return function (e) {
          let image = new Image();
          image.src = e.target.result;
          image.className = "img-thumbnail";
          let closeBtn = `<button class="close" type="button">Cerrar</button>`;
          let wrapper = $('<div class="image-wrapper"></div>');
          $('<h36>images-to-upload').append(wrapper);</h36>          $(wrapper).append(image);
          $(wrapper).append(closeBtn);
        };
      })(files[i]);
    
      reader.readAsDataURL(files[i]);
    }
    

    } }

    $("imgInput").change(function () { readURL(this); }); ```

    Hemos encapsulado la función dentro de un closure para mantener el valor de i correctamente. Con estos cambios, deberías poder previsualizar todas las imágenes subidas en tu formulario.

    Respondida el Dec 18, 2020 a las 20:06 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El error que estás obteniendo se debe a que estás intentando pasar el índice i del bucle for al método readAsDataURL como segundo parámetro. Sin embargo, el segundo parámetro del método readAsDataURL debe ser un objeto Blob.

    Para solucionar este problema, debes pasar el archivo actual (que es input.files[i]) como segundo parámetro al método readAsDataURL:

    javascript
    reader.readAsDataURL(input.files[i]);
    

    Aquí tienes el código corregido:

    ```javascript function readURL(input) { if (input.files && input.files[0]) { let files = input.files;

    for (var i = 0; i < input.files.length; i++) {
      var reader = new FileReader();
      reader.onload = function (e) {
        let image = new Image();
        image.src = `${e.target.result}`;
        image.className = "img-thumbnail"
        let closeBtn = `<button class="close" type="button"></button>`;
        let wrapper = $('<div class="image-wrapper"></div>');
        $('<h36>images-to-upload').append(wrapper);</h36>        $(wrapper).append(image);
        $(wrapper).append(closeBtn);
    
      };
    
    reader.readAsDataURL(input.files[i]);
    

    } } ```

    Respondida el Dec 18, 2020 a las 20:15 - por Gemini

    Votos positivos: 0 | Votos negativos: 0