Leia arquivos em JavaScript
Como selecionar arquivos, ler metadados e conteúdo de arquivos e monitorar o progresso de leitura.
Poder selecionar e interagir com arquivos no dispositivo local do usuário é um dos recursos mais usados da web. Ele permite que os usuários selecionem arquivos e os enviem para um servidor, por exemplo, transferindo fotos ou documentos fiscais, etc. Mas, também permite que os sites os leiam e manipulem sem nunca ter que transferir os dados pela rede.
A moderna API File System Access #
A API File System Access, que permite o acesso ao sistema de arquivos, fornece uma maneira fácil de ler e gravar em arquivos e diretórios no sistema local do usuário. Atualmente ela está disponível na maioria dos navegadores derivados do Chromium, como Chrome ou Edge. Para saber mais sobre isso, consulte o artigo API File System Access.
Como a API File System Access ainda não é compatível com todos os navegadores, dê uma olhada na biblioteca browser-fs-access, uma biblioteca auxiliar que usa a nova API onde quer que esteja disponível, mas volta para abordagens legadas quando ela não estiver.
Trabalhando com arquivos, da maneira clássica #
Este guia mostra como:
- Selecionar arquivos
- Ler os metadados do arquivo
- Ler o conteúdo de um arquivo
Selecionar arquivos #
Elemento input do HTML #
A maneira mais fácil de permitir que os usuários selecionem arquivos é usando o elemento <input type="file">
, que é suportado todos os principais navegadores. Quando clicado, ele permite que um usuário selecione um arquivo (ou vários arquivos se o atributo multiple
estiver incluído), usando a interface de usuário de seleção de arquivo integrada do sistema operacional. Quando o usuário termina de selecionar um arquivo ou arquivos, o evento change
do elemento é disparado. Você pode acessar a lista de arquivos através de event.target.files
, que é um objeto FileList
. Cada item em 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>
Este exemplo permite que um usuário selecione vários arquivos usando a IU de seleção de arquivo integrada do sistema operacional e, a seguir, registra cada arquivo selecionado no console.
Limite os tipos de arquivos que o usuário pode selecionar #
Em alguns casos, você pode querer limitar os tipos de arquivos que os usuários podem selecionar. Por exemplo, um aplicativo de edição de imagens deve aceitar apenas imagens, não arquivos de texto. Para fazer isso, você pode adicionar um accept
ao elemento de entrada para especificar quais arquivos são aceitos.
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
Arrastar e soltar personalizado #
Em alguns navegadores, o elemento <input type="file">
também é um destino para soltar, permitindo que os usuários arrastem e soltem arquivos em seu aplicativo. Mas, o alvo de soltar é pequeno e pode ser difícil de usar. Em vez disso, depois de fornecer a funcionalidade principal usando um elemento <input type="file">
, você deve fornecer uma grande superfície personalizada de arrastar e soltar.
Escolha sua zona de soltar #
Sua superfície de soltar dependerá do design de sua aplicação. Você pode querer que apenas parte da janela seja uma superfície de soltar ou, potencialmente, a janela inteira.

O Squoosh permite que o usuário arraste e solte uma imagem em qualquer lugar da janela, e clicar em selecionar uma imagem invoca o elemento <input type="file">
. Independentemente do que você escolher como zona para soltar, certifique-se de que esteja claro para o usuário que ele pode arrastar e soltar arquivos nessa superfície.
Defina a zona de soltar #
Para permitir que um elemento seja uma zona de arrastar e soltar, você precisará escutar dois eventos, dragover
e drop
. O dragover
atualiza a IU do navegador para indicar visualmente que a ação arrastar e soltar está criando uma cópia do arquivo. O drop
é disparado depois que o usuário solta os arquivos na superfície. Semelhante ao elemento input, você pode acessar a lista de arquivos em event.dataTransfer.files
, que é um objeto FileList
. Cada item 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()
impedem que o comportamento default do navegador aconteça e permitem que seu código seja executado. Sem eles, o navegador navegaria para fora da sua página e abriria os arquivos que o usuário colocou na janela do navegador.
Confira Arrastar e soltar personalizado para uma demonstração ao vivo.
E quanto aos diretórios? #
Infelizmente, hoje não existe uma boa maneira de obter acesso a um diretório.
O webkitdirectory
no elemento <input type="file">
permite que o usuário escolha um diretório ou diretórios. É compatível com alguns navegadores baseados em Chromium e possivelmente no Safari para desktop, mas tem relatos conflitantes quanto à compatibilidade de navegadores.
Se o comportamento de arrastar e soltar estiver ativado, um usuário pode tentar arrastar um diretório para a zona de soltar. Quando o evento drop for disparado, ele incluirá um objeto File
para o diretório, mas não poderá acessar nenhum dos arquivos do diretório.
Ler os metadados do arquivo #
O objeto File
contém várias propriedades de metadados sobre o arquivo. A maioria dos navegadores fornece o nome do arquivo, o tamanho do arquivo e o tipo MIME, embora dependendo da plataforma, navegadores diferentes possam fornecer informações diferentes ou adicionais.
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});
}
}
Você pode ver isto em ação na demonstração Glitch do input-type-file
Ler o conteúdo de um arquivo #
Para ler um arquivo, use FileReader
, que permite ler o conteúdo de um objeto File
na memória. Você pode instruir o FileReader
a ler um arquivo como um array buffer, uma 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);
}
O exemplo acima lê um File
fornecido pelo usuário, depois o converte em uma URL de dados e usa essa URL de dados para exibir a imagem em um elemento img
. Veja o Glitch read-image-file
para saber como verificar se o usuário selecionou um arquivo de imagem.
Monitore o progresso de um arquivo lido #
Ao ler arquivos grandes, pode ser útil fornecer alguma experiência ao usuário para indicar o quanto a leitura progrediu. Para isso, use o evento progress
fornecido pelo FileReader
. O evento progress
fornece duas propriedades, loaded
, a quantidade lida e total
, a quantidade total a ser lida.
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 do herói por Vincent Botta de Unsplash