Ler arquivos em JavaScript

Selecionar e interagir com arquivos no dispositivo local do usuário é uma das os recursos da Web mais usados. Ele permite que os usuários selecionem arquivos e fazer o upload deles para um servidor, por exemplo, ao compartilhar fotos ou enviar impostos documentos. Ele também permite que os sites os leiam e manipulem sem nunca ter para transferir os dados pela rede. Nesta página, mostramos como usar JavaScript para interagir com arquivos.

A API moderna File System Access

A API File System Access fornece uma maneira de ler e gravar em arquivos e diretórios no sistema local do usuário. Ela está disponível na maioria dos navegadores como o Chrome e o Edge. Para saber mais, consulte A API File System Access.

Como a API File System Access não é compatível com todos os navegadores, nós recomendamos usar browser-fs-access, uma biblioteca auxiliar que usa a nova API sempre que ela estiver disponível e se encaixa a abordagens legadas quando não são.

Trabalhar com arquivos à maneira clássica

Neste guia, mostramos como interagir com arquivos usando métodos JavaScript legados.

Selecionar arquivos

Há duas maneiras principais de selecionar arquivos: usando elemento de entrada HTML, e usando um zona com recurso de arrastar e soltar.

Elemento de entrada HTML

A maneira mais fácil para os usuários selecionarem arquivos é usando a <input type="file"> compatível com os principais navegadores. Quando clicado, permite que um usuário selecionar um arquivo ou vários arquivos se o multiple é incluído, usando a seleção de arquivos integrada do sistema operacional de ML pela IU. Quando o usuário termina de selecionar um ou mais arquivos, o elemento change é acionado. Você pode acessar a lista de arquivos de event.target.files, que é um objeto FileList. Cada item na FileList é um 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>

O exemplo a seguir permite que um usuário selecione vários arquivos usando o comando IU de seleção de arquivos integrada do sistema e, em seguida, registra cada arquivo selecionado no no console do Google Cloud.

Limitar os tipos de arquivos que os usuários podem selecionar

Em alguns casos, talvez você queira limitar os tipos de arquivo que os usuários podem selecionar. Para exemplo, um app de edição de imagens deve aceitar apenas imagens, não arquivos de texto. Para definir restrições de tipo de arquivo, adicione uma accept ao elemento de entrada para especificar quais tipos de arquivo são aceitos:

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

Recurso de arrastar e soltar personalizado

Em alguns navegadores, o elemento <input type="file"> também é um destino de soltar, permitindo que os usuários arrastem e soltem arquivos no app. No entanto, esse destino de soltar é pequeno e pode ser difícil de usar. Em vez disso, depois de fornecer os recursos principais usando um elemento <input type="file">, é possível fornecer um recurso de arrastar e soltar grande e personalizado superfície

Escolha a zona de soltar

A superfície depende do design do aplicativo. Talvez você queira apenas parte da janela como uma superfície em queda, mas você pode usar a janela inteira.

Uma captura de tela do Squoosh, um app da Web de compactação de imagens.
O Squoosh transforma a janela em uma zona de soltar.

O aplicativo de compactação de imagens Squoosh permite que o usuário arraste uma imagem para qualquer lugar na e clique em select an image para invocar o <input type="file"> . Independente da sua zona de destino, ela precisa estar clara para o usuário para poder arrastar arquivos até essa superfície.

Definir a zona de soltar

Para ativar um elemento como uma zona de arrastar e soltar, crie listeners para dois eventos: dragover e drop. O evento dragover atualiza a interface do navegador para indicar visualmente que o arrastar e soltar é criar uma cópia do arquivo. O evento drop é disparado depois que o usuário solta os arquivos na superfície. Assim como no elemento de entrada, pode acessar a lista de arquivos do event.dataTransfer.files, que é um objeto FileList. Cada em FileList é um 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() e event.preventDefault() interromper o comportamento padrão do navegador e deixar seu código ser executado. Sem eles, o navegador sairia da página e abriria os arquivos o usuário entrou na janela do navegador.

Para uma demonstração ao vivo, consulte Arrastar e soltar personalizados.

E os diretórios?

Infelizmente, não existe uma boa maneira de acessar um diretório usando JavaScript.

O webkitdirectory no elemento <input type="file"> permite que o usuário escolha um diretório ou diretórios. Ele é compatível com a maioria dos principais navegadores exceto para Firefox para Android e Safari para iOS.

Se o recurso de arrastar e soltar estiver ativado, um usuário poderá tentar arrastar um diretório para o na zona de soltar. Quando o evento de soltar é disparado, ele inclui um objeto File para o mas não fornece acesso a nenhum dos arquivos no diretório.

Ler metadados do arquivo

O objeto File contém metadados sobre o arquivo. A maioria dos navegadores fornecem o nome do arquivo, o tamanho do arquivo e o tipo MIME, mas dependendo na plataforma, diferentes navegadores podem oferecer diferentes informações imprecisas ou inadequadas.

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

Saiba como isso funciona no input-type-file demonstração.

Ler o conteúdo de um arquivo

Use FileReader para lê o conteúdo de um objeto File na memória; Você pode pedir para o FileReader lê um arquivo como um buffer de matriz, um URL de dados, ou 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);
}

Este exemplo lê um File fornecido pelo usuário e o converte em um arquivo URL e usa esse URL de dados para mostrar a imagem em um elemento img. Para saber como verificar se o usuário selecionou um arquivo de imagem, consulte a Demonstração do read-image-file.

Monitorar o progresso da leitura de um arquivo

Ao ler arquivos grandes, pode ser útil fornecer alguma UX para informar ao usuário o progresso da leitura. Para isso, use o método progress evento fornecido por FileReader. O evento progress tem duas propriedades: loaded (o valor lido) e total (o valor a ser lido).

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

Imagem principal de Vincent Botta, do Unsplash