Monitorando Progresso de Upload de Arquivos - JavaScript
Quando lidamos com uploads de arquivos grandes utilizando a File API, é importante fornecer feedback visual ao usuário sobre o progresso da operação. O tipo FileReader
progress
ProgressEvent
: uma propriedade booleana que indica se é possível calcular o progresso (isto é, o número de bytes lidos em relação ao total).lengthComputable
: número inteiro sem sinal de 64 bits que indica a quantidade de dados já carregados.loaded
: número inteiro sem sinal de 64 bits que representa o total de dados a serem carregados.total
O exemplo a seguir demonstra como mplementar essa funcionalidade:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<title>Monitoramento de Progresso</title>
<style>
#progress {
width: 0;
height: 100%;
background-color: #ccc;
}
#progress-bar {
width: 100px;
height: 20px;
border: 1px solid #888;
}
</style>
</head>
<body>
<input type="file" id="files" multiple><br><br>
<div id="progress-bar">
<div id="progress"></div>
</div>
<script>
const progressBar = document.getElementById("progress-bar");
const progress = document.getElementById("progress");
// Atualiza o progresso do upload
function updateProgress(e) {
if (e.lengthComputable) {
const percentLoaded = Math.round((e.loaded / e.total) * 100);
if (percentLoaded < 100) {
progress.style.width = percentLoaded + "%";
progress.textContent = percentLoaded + "%";
}
}
}
// Gerencia a seleção de arquivos
function handleFileSelected(event) {
progress.style.width = "0%";
progress.textContent = "0%";
const reader = new FileReader();
reader.onprogress = updateProgress;
reader.onerror = (e) => console.error("Erro ao ler o arquivo:", e.target.error);
reader.onload = () => {
progress.style.width = "100%";
progress.textContent = "100%";
};
if (event.target.files.length > 0) {
reader.readAsBinaryString(event.target.files[0]);
}
}
document.getElementById("files").addEventListener("change", handleFileSelected);
</script>
</body>
</html>
Neste exemplo, o elemento <input> com o atributo type="file"
<div id="progress-bar">
<div id="progress">
A função handleFileSelected
progress.style.width = "0%";
progress.textContent = "0%";
Em seguida, criamos uma instância de FileReader
Cálculo do Progresso
O evento progress
function updateProgress(e) {
if (e.lengthComputable) {
const percentLoaded = Math.round((e.loaded / e.total) * 100);
if (percentLoaded < 100) {
progress.style.width = percentLoaded + "%";
progress.textContent = percentLoaded + "%";
}
}
}
O aumento gradual da largura do elemento progress, com um fundo cinza, serve como um indicador visual claro. O texto interno exibe a porcentagem carregada.
Quando o arquivo é carregado completamente, o evento load do FileReader é disparado. Neste ponto, o indicador de progresso é atualizado para refletir a finalização.
reader.onload = () => {
progress.style.width = "100%";
progress.textContent = "100%";
};
Para iniciar a leitura do arquivo como uma sequência de bytes, utilizamos o método readAsBinaryString
if (event.target.files.length > 0) {
reader.readAsBinaryString(event.target.files[0]);
}