Определение окончания загрузки файла браузером: решения

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы определить момент начала загрузки файла, следите за cookie, установленной сервером. Проверяйте наличие cookie при помощи JavaScript с определенными интервалами. Когда cookie будет обнаружена, прекратите проверку и выполните операции, которые должны быть проведены после начала загрузки.

JS
Скопировать код
let checkDownload = setInterval(() => {
    if (document.cookie.includes('download_token=12345')) {
        clearInterval(checkDownload);
        alert('Файл начал загружаться.');
        document.cookie = 'download_token=; Max-Age=-99999999;'; 
    }
}, 1000);

Используйте уникальные идентификаторы в cookie для контроля параллельных процессов загрузок.

Кинга Идем в IT: пошаговый план для смены профессии

Дополнительные стратегии

Всплывающее уведомление с window.onblur()

Для точного определения момента начала загрузки файла, можно использовать метод window.onblur(). Это позволит отследить момент, когда системный диалог браузера переместит фокус, что возможно, произойдет из-за начала загрузки.

JS
Скопировать код
window.onblur = function() {  
  if (document.cookie.includes('download_token=12345')) {
    // подготовка к просмотру
  }
};

Безопасность — превыше всего!

Для улучшения безопасности используйте флаги httpOnly и Secure при установке cookie:

php
Скопировать код
setcookie("download_token", "12345", 0, "/", "", true, true);

Использование потоков

При работе с большим объемом данных стоит рассмотреть применение потокового ввода-вывода:

JS
Скопировать код
fetch('file/stream/url')
  .then(response => response.body.pipeTo(new WritableStream(/* ... */)))
  .then(() => console.log('Загрузка завершена!'));

Визуализация

Сравните окно браузера с домом (🏠), ожидающим посылку (📦).

Загрузка файла начинается, когда грузовик (🚚) выезжает со склада:

🚚💨 (Начинается загрузка файла)

Когда звонит дверной звонок, мы понимаем, что посылка доставлена!

document.addEventListener('onPackageReceived', function() { alert('🔔 Динь-донг! Ваш файл 📦 был доставлен 🏠!'); });

Браузер уведомляет о загрузке файла, как о получении посылки на порог дома.

🏠💡📸: Динь-донг! Файл 📦 загружен!

Умный дом — теперь это реальность!

Продвинутые подходы и особые случаи

Несколько загрузок? Тут проблем не будет!

Примените соответствие между токенами и загрузками для контроля за несколькими процессами загрузки:

JS
Скопировать код
let downloads = {
  token1: { status: 'initializing' },
  token2: { status: 'downloading' },
};

// Проверяем статус по токену

Таймаут и слабые ссылки

Установите таймер на удаление интервальной проверки, если загрузка не обнаружена в течение установленного периода:

JS
Скопировать код
setTimeout(() => clearInterval(checkDownload), 10000);

Чтобы предотвратить утечки памяти, активно освобождайте использованные ресурсы:

JS
Скопировать код
window.onfocus = () => clearInterval(checkDownload);

Пуллинг с помощью AJAX

Получайте статус загрузки от сервера, регулярно отправляя AJAX-запросы:

JS
Скопировать код
function checkDownloadStatus(token) {
  // Запрашиваем у сервера статус загрузки
}

iframe

Запустите загрузку внутри скрытого iframe и следите за его состоянием загрузки:

JS
Скопировать код
let downloadIframe = document.createElement('iframe');
downloadIframe.style.display = 'none';
downloadIframe.src = 'download/url/with/token';
document.body.appendChild(downloadIframe);

Важность UX

Держите пользователя в курсе процесса загрузки:

JS
Скопировать код
document.getElementById('loading').style.display = 'block';

document.cookie = 'downloaded=; Max-Age=-99999999;';
document.getElementById('loading').style.display = 'none';

Полезные материалы

  1. Использование Fetch API — об использовании Fetch API для мониторинга прогресса загрузки.
  2. Fetch – javascript.info — знакомство с Fetch API в JavaScript.
  3. GitHub – eligrey/FileSaver.js — библиотека для сохранения файлов на стороне клиента.
  4. Window: событие load — о событии загрузки окна.
  5. GitHub – jimmywarting/StreamSaver.js — библиотека для записи потоков на стороне клиента.