При загрузке больших файлов через File API может быть полезно информировать пользователей о ходе операции чтения. Для этой цели тип FileReader позволяет обрабатывать событие progress. В обработчик этого события передается объект, который имеет тип ProgressEvent и который предоставляет следующие свойства:
lengthComputable: булевое свойство, которое указывает, можно ли вычислить прогресс (количество прочитанных байтов) или нет.
loaded: 64-битное целое число без знака, которое указывает на объем уже загруженных данных
total: 64-битное целое число без знака, которое хранит общее количество загружаемых данных
Например, возьмем следующую страницу:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>METANIT.COM</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");
// отслеживаем прогресс загрузки
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 + "%";
}
}
}
// обрабатываем выбор файлов
function handleFileSelected(event) {
progress.style.width = "0%";
progress.textContent = "0%";
const reader = new FileReader();
reader.onprogress = updateProgress;
reader.onerror = (e) => console.error(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>
На странице определен элемент <input> для выбора файла. Для индикации загрузки файла на странице определен элемент
<div id="progress-bar"> с вложенным элементом <div id="percent">.
В качестве обработчика события change для этого элемента <input>
используется функция handleFileSelected. В ней устанавливаем начальные значения для индикатора загрузки:
progress.style.width = "0%"; progress.textContent = "0%";
Затем создаем объект FileReader и для его события progress в качестве обработчика применяем функцию updateProgress. В ней рассчитываем текущее состояние загрузки и соответствующим образом обновляем ширину и текст элемента 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 + "%";
}
}
}
Поскольку для элемента progress используется серый фоновый цвет, то увеличение ширины приведет к увеличению закрашенной области, что будет индикатором загрузки. И кроме того, по тексту элемента мы сможем увидеть процент данных загруженного файла.
Когда загрузка завершена, у объекта FileReader срабатывает событие load, в котором устанавливаем финальные значения для элемента progress.
reader.onload = () => {
progress.style.width = "100%";
progress.textContent = "100%";
};
В конце обработчика выбора файла начинаем его загрузку как набора байтов:
if(event.target.files.length>0) reader.readAsBinaryString(event.target.files[0]);
Для демонстрации обработки прогресса загрузки здесь никак загруженные данные не используются, но естественно мы можем получить эти данные, как описывалось в прошлой статье, и каким-нибудь образом использовать.
Таким образом, при выборе файла начнется загрузка, а элемент progress отобразит индикацию загрузки.