Lee archivos en JavaScript

Seleccionar archivos e interactuar con ellos en el dispositivo local del usuario es una de las y las funciones más usadas de la Web. Permite a los usuarios seleccionar archivos y subirlas a un servidor, por ejemplo, cuando compartas fotos o envíes impuestos documentos. También permite que los sitios los lean y manipulen sin tener que para transferir los datos a través de la red. En esta página, se explica cómo usar JavaScript para interactuar con los archivos.

La moderna API de File System Access

La API de File System Access permite leer y escribir archivos y directorios en el sistema local del usuario. Están disponibles en la mayoría navegadores como Chrome y Edge. Para obtener más información, consulta La API de File System Access

Como la API de File System Access no es compatible con todos los navegadores, recomendamos usar browser-fs-access, una biblioteca auxiliar que usa la nueva API siempre que esté disponible volver a los enfoques heredados cuando no lo es.

Trabaja con archivos de la forma clásica

En esta guía, se muestra cómo interactuar con archivos usando métodos heredados de JavaScript.

Seleccionar archivos

Existen dos formas principales de seleccionar archivos: el elemento de entrada HTML, y el uso de un zona de arrastrar y soltar.

Elemento de entrada HTML

La forma más sencilla para que los usuarios seleccionen archivos es usar el <input type="file"> que es compatible con todos los navegadores principales. Cuando un usuario hace clic en él, seleccionar uno o varios archivos si el multiple se incluye el atributo con la selección de archivos integrados del sistema operativo de la IU de Google. Cuando el usuario termina de seleccionar uno o más archivos, el change del elemento se activa el evento. Puedes acceder a la lista de archivos desde event.target.files, que es un objeto FileList. Cada elemento de FileList es un objeto File.

<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
  const fileSelector = document.getElementById('file-selector');
  fileSelector.addEventListener('change', (event) => {
    const fileList = event.target.files;
    console.log(fileList);
  });
</script>

El siguiente ejemplo permite que un usuario seleccione varios archivos con su de selección de archivos integrada del sistema y, luego, registra cada archivo seleccionado de Cloud.

Limita los tipos de archivos que los usuarios pueden seleccionar

En algunos casos, es posible que desees limitar los tipos de archivos que los usuarios pueden seleccionar. Para Por ejemplo, una app de edición de imágenes solo debería aceptar imágenes, no archivos de texto. Para establecer restricciones de tipo de archivo, agrega accept al elemento de entrada para especificar qué tipos de archivos se aceptan:

<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">

Arrastrar y soltar contenido personalizado

En algunos navegadores, el elemento <input type="file"> también es un destino para soltar, y permitir que los usuarios arrastren y suelten archivos en la app. Sin embargo, este objetivo de soltar es pequeño y difícil de usar. En su lugar, después de proporcionar las funciones principales un elemento <input type="file">, puedes proporcionar una acción grande y personalizada de arrastrar y soltar de ataque de la nube.

Elige tu zona de caída

La superficie de caída depende del diseño de la aplicación. Quizá solo quieras de la ventana para que sea una superficie de caída, pero puedes usar toda la ventana.

Una captura de pantalla de Squoosh, una app web de compresión de imágenes.
El efecto squoosh hace que toda la ventana sea una zona de caída.

La aplicación de compresión de imágenes Squoosh permite que el usuario arrastre una imagen a cualquier parte del y haz clic en seleccionar una imagen para invocar el <input type="file"> . Sin importar la que elijas como zona de caída, asegúrate de que sea clara para el usuario que pueden arrastrar archivos a esa superficie.

Define la zona de soltar

Para habilitar un elemento como zona de arrastrar y soltar, crea objetos de escucha para dos eventos: dragover y drop. El evento dragover actualiza la IU del navegador para indicar visualmente que el de arrastrar y soltar es crear una copia del archivo. Se activa el evento drop después de que el usuario suelta los archivos en la superficie. Al igual que con el elemento de entrada, puedes acceder a la lista de archivos desde event.dataTransfer.files, que es un objeto FileList. Cada El elemento de FileList es un objeto File.

const dropArea = document.getElementById('drop-area');

dropArea.addEventListener('dragover', (event) => {
  event.stopPropagation();
  event.preventDefault();
  // Style the drag-and-drop as a "copy file" operation.
  event.dataTransfer.dropEffect = 'copy';
});

dropArea.addEventListener('drop', (event) => {
  event.stopPropagation();
  event.preventDefault();
  const fileList = event.dataTransfer.files;
  console.log(fileList);
});

event.stopPropagation() y event.preventDefault() detener el comportamiento predeterminado del navegador y dejar que se ejecute el código. Sin ellas, el navegador se alejaría de la página y abriría los archivos el usuario soltó en la ventana del navegador.

Para ver una demostración en vivo, consulta Arrastrar y soltar personalizados.

¿Qué ocurre con los directorios?

Lamentablemente, no hay una buena manera de acceder a un directorio con JavaScript.

La webkitdirectory en el elemento <input type="file"> permite al usuario elegir un directorio o directorios. Es compatible con la mayoría de los navegadores principales. excepto por Firefox para Android y Safari en iOS.

Si la función de arrastrar y soltar está habilitada, un usuario podría intentar arrastrar un directorio al zona de descarte. Cuando se activa el evento de soltar, incluye un objeto File para el del directorio, pero no proporciona acceso a ninguno de los archivos en él.

Leer metadatos de archivos

El objeto File contiene metadatos sobre el archivo. La mayoría de los navegadores proporcionan el nombre de archivo, el tamaño del archivo y el tipo de MIME, aunque, en la plataforma, es posible que los diferentes navegadores proporcionen diferentes información.

function getMetadataForFileList(fileList) {
  for (const file of fileList) {
    // Not supported in Safari for iOS.
    const name = file.name ? file.name : 'NOT SUPPORTED';
    // Not supported in Firefox for Android or Opera for Android.
    const type = file.type ? file.type : 'NOT SUPPORTED';
    // Unknown cross-browser support.
    const size = file.size ? file.size : 'NOT SUPPORTED';
    console.log({file, name, type, size});
  }
}

Puedes ver esto en acción en la input-type-file. demostración.

Cómo leer el contenido de un archivo

Usa FileReader para leer el contenido de un objeto File en la memoria. Puedes decirle a FileReader que leer un archivo como un búfer de array una URL de datos o texto:

function readImage(file) {
  // Check if the file is an image.
  if (file.type && !file.type.startsWith('image/')) {
    console.log('File is not an image.', file.type, file);
    return;
  }

  const reader = new FileReader();
  reader.addEventListener('load', (event) => {
    img.src = event.target.result;
  });
  reader.readAsDataURL(file);
}

En este ejemplo, se lee un File proporcionado por el usuario y, luego, se lo convierte en un y usa esa URL de datos para mostrar la imagen en un elemento img. Para aprender a verificar que el usuario haya seleccionado un archivo de imagen, consulta el Demostración de read-image-file.

Supervisa el progreso de lectura de un archivo

Cuando leas archivos grandes, puede ser útil proporcionar algo de UX para decirle al usuario el progreso de la lectura. Para eso, usa la progress evento proporcionado por FileReader. El evento progress tiene dos propiedades: loaded (la cantidad leída) y total (la cantidad que se leerá).

function readFile(file) {
  const reader = new FileReader();
  reader.addEventListener('load', (event) => {
    const result = event.target.result;
    // Do something with result
  });

  reader.addEventListener('progress', (event) => {
    if (event.loaded && event.total) {
      const percent = (event.loaded / event.total) * 100;
      console.log(`Progress: ${Math.round(percent)}`);
    }
  });
  reader.readAsDataURL(file);
}

Imagen hero de Vincent Botta de Unsplash