При загрузке больших файлов через 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 отобразит индикацию загрузки.