004. Uploader con Ajax (2)

En el capítulo anterior vimos como subir al servidor con la ayuda de AJAX ficheros. Hicimos la función en Javascript que nos permite desencadenar la conexión al archivo PHP, esta función se llamaba uploader(), y posteriormente hicimos el código PHP que permite subir el archivo y devolver una respuesta que posteriormente formateábamos a código JSON.

En este capítulo vamos a añadir una barra de progreso a nuestro archivo, para lo cual, HTML dispone de una etiqueta denominada <progress></progress>, la cual recibe dos atributos, value, que es el valor actual y max, que define la máxima anchura que va a recibir la barra de progreso.

Dependiendo del navegador en el que estemos, esta barra de progreso puede variar el diseño, ya que cada navegador lo maneja de manera nativa, como ocurre con los reproductores de audio y video.

Esta barra de progreso la vamos a crear dinámicamente por cada archivo que se suba, y cuando ya se haya terminado de cargar el archivo, dejaremos unos segundos y va a desaparecer dicha barra.

Vamos a necesitar una función que vaya trabajando toda la parte del progreso, función que llamaremos progressUpload() en nuestro archivos uploader.html.

Veamos la sintaxis de uploader.html.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Uploader con AJAX</title>
    <style>
      html {
        box-sizing: border-box;
        font-family: sans-serif;
        font-size: 16px;
      }

      *,
      *::after,
      *::before {
        box-sizing: inherit;
      }

      main {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        text-align: center;
        min-height: 100vh;
      }

      progress {
        margin-top: 1rem;
      }
    </style>
  </head>

  <body>
    <main>
      <input type="file" name="files" id="files" multiple />
    </main>

    <script>
      const d = document,
        $main = d.querySelector("main"),
        $files = d.getElementById("files");

      // Creamos función que mediante AJAX permita subir la carga de archivos
      // Esta función se ejecutará por cada archivo que reciba el input

      const uploader = (file) => {
        const xhr = new XMLHttpRequest(),
          formData = new FormData();

        formData.append("file", file);

        xhr.addEventListener("readystatechange", (e) => {
          if (xhr.readyState !== 4) return;

          if (xhr.status >= 200 && xhr.status < 300) {
            let json = JSON.parse(xhr.responseText);
            console.log(json);
          } else {
            let message = xhr.statusText || "Ocurrió un error";
            console.log(`Error ${xhr.status}: ${message}`);
          }
        });

        xhr.open("POST", "uploader.php");
        xhr.setRequestHeader("enc-type", "multipart/form-data");
        xhr.send(formData);
      };

      const progressUpload = (file) => {
        const $progress = d.createElement("progress"),
          $span = d.createElement("span");
        $progress.value = 0;
        $progress.max = 100;

        $main.insertAdjacentElement("beforeend", $progress);
        $main.insertAdjacentElement("beforeend", $span);

        const fileReader = new FileReader();

        fileReader.readAsDataURL(file);

        fileReader.addEventListener("progress", (e) => {
          let progress = parseInt((e.loaded * 100) / e.total);
          $progress.value = progress;
          $span.innerHTML = `<b>${file.name} - ${progress}%</b>`;
        });

        fileReader.addEventListener("loadend", (e) => {
          uploader(file);

          setTimeout(() => {
            $main.removeChild($progress);
            $main.removeChild($span);
            $files.value = "";
          }, 3000);
        });
      };

      d.addEventListener("change", (e) => {
        if (e.target === $files) {
          const files = Array.from(e.target.files);
          files.forEach((el) => progressUpload(el));
        }
      });
    </script>
  </body>
</html>

Dejamos todos los ficheros del ejercicios en formato ZIP.

Scroll al inicio