Artigo original: How to upload single or multiple files the easy way with FormData
Neste artigo, aprenderemos sobre a interface FormData, disponível nos navegadores modernos da web como parte das especificações do HTML5.
Veremos exemplos de uso de FormData com Ajax e indicaremos links para o uso com Angular 7, Ionic e React.
O que é a FormData?
FormData é, simplesmente, uma estrutura de dados que pode ser usada para armazenar pares chave-valor. Assim como sugere o seu nome, ela foi projetada para manter dados de formulários, ou seja, você pode usá-la com o JavaScript para criar um objeto que corresponda a um formulário de HTML. Em geral, ela é útil quando precisamos enviar dados do formulário para endpoints de uma API RESTful, por exemplo, para fazer o upload de um ou de vários arquivos usando a interface XMLHttpRequest
, a API fetch()
ou o Axios.
Você pode criar um objeto na FormData instanciando a interface FormData usando o operador new
, conforme segue:
const formData = new FormData()
A referência de formData
é a uma instância de FormData. Você pode chamar diversos métodos no objeto para adicionar e trabalhar com pares de dados. Cada par tem uma chave e um valor.
Esses são os métodos disponíveis nos objetos de FormData:
append()
: usado para anexar um par chave-valor ao objeto. Se a chave já existir, o valor é anexado ao valor original daquela chave;delete()
: usado para excluir um par chave-valor;entries()
: retorna um objeto Iterator que você pode usar para percorrer o objeto na forma de uma lista de seus pares chave-valor;get()
: usado para retornar o valor de uma chave. Se vários valores forem anexados, retorna o primeiro valor;getAll()
: usado para retornar todos os valores de uma chave específica;has()
: usado para verificar se uma chave existe;keys()
: retorna um objeto Iterator que você pode usar para listar as chaves disponíveis do objeto;set()
: usado para adicionar um valor ao objeto com a chave especificada. Ele substituirá o valor caso a chave já exista;values()
: retorna um objeto Iterator para os valores do objeto FormData.
Exemplo de upload de arquivos em JavaScript puro
Vamos ver agora um exemplo simples de upload de arquivos usando o JavaScript puro, XMLHttpRequest
e FormData
.
Navegue até a pasta de trabalho e crie o arquivo index.html
com o seguinte conteúdo:
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="app"></div>
<script src="index.js">
</script>
</body>
</html>
Simplesmente criamos um documento HTML com uma <div>
identificada pelo id app
. Em seguida, incluímos o arquivo index.js
usando uma tag <script>
.
Depois, criamos o arquivo index.js
e adicionamos a ele o código abaixo:
document.getElementById("app").innerHTML = `
<h1>File Upload & FormData Example</h1>
<div>
<input type="file" id="fileInput" />
</div>
`;
const fileInput = document.querySelector("#fileInput");
const uploadFile = file => {
console.log("Uploading file...");
const API_ENDPOINT = "https://file.io";
const request = new XMLHttpRequest();
const formData = new FormData();
request.open("POST", API_ENDPOINT, true);
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log(request.responseText);
}
};
formData.append("file", file);
request.send(formData);
};
fileInput.addEventListener("change", event => {
const files = event.target.files;
uploadFile(files[0]);
});
Primeiro, inserimos um elemento <input type="file" id="fileInput" />
em nossa página HTML. Ele será usado para selecionar o arquivo do qual faremos o upload.
Então, consultamos o elemento de entrada de arquivo usando o método querySelector()
.
Depois, definimos o método uploadFile()
no qual, primeiro, declaramos uma variável API_ENDPOINT
, que mantém o endereço de nosso endpoint para o upload do arquivo. Em seguida, criamos uma solicitação a XMLHttpRequest
e um objeto FormData
vazio.
Usamos o método append
de FormData para anexar o arquivo, passado como parâmetro para o método uploadFile()
, para a chave file
. Isso criará um par chave-valor com file
como chave e o conteúdo do arquivo passado como valor.
Após fazermos isso, enviamos a solicitação usando o método send()
de XMLHttpRequest
e passamos o objeto FormData
como argumento.
Depois de definir o método uploadFile()
, escutamos o evento de alteração no elemento <input>
e chamamos o método uploadFile()
com o arquivo selecionado como argumento. O arquivo é acessado pelo array event.target.files
.
Você pode experimentar com o exemplo deste sandbox de código:
Fazendo o upload de vários arquivos
Você pode facilmente modificar o código acima para dar suporte ao upload de vários arquivos.
Primeiro, você precisa adicionar a propriedade multiple
ao elemento <input>
:
<input type="file" id="fileInput" multiple />
Agora, você poderá selecionar diversos arquivos da sua unidade.
Em seguida, altere o método uploadFile()
para que aceite um array de arquivos como argumento e simplesmente percorra o array e anexe os arquivos ao objeto de FormData
:
const uploadFile = (files) => {
console.log("Uploading file...");
const API_ENDPOINT = "https://file.io";
const request = new XMLHttpRequest();
const formData = new FormData();
request.open("POST", API_ENDPOINT, true);
request.onreadystatechange = () => {
if (request.readyState === 4 && request.status === 200) {
console.log(request.responseText);
}
};
for (let i = 0; i < files.length; i++) {
formData.append(files[i].name, files[i])
}
request.send(formData);
};
Por fim, chame o método com um array de arquivos como argumento:
fileInput.addEventListener("change", event => {
const files = event.target.files;
uploadFile(files);
});
Quando tiver a oportunidade, confira esses tutoriais avançados (em inglês) sobre como usar FormData
com Angular, Ionic e React: