Введение

Представьте: вы уже три часа ждёте, пока докачается 40-гигабайтный образ виртуальной машины для локального тест-стенда (ну потому что «работает на моей машине» — это святое), как вдруг на 98% пропадает интернет. Перезагрузка страницы — и Firefox хладнокровно начинает всё сначала. Знакомая боль? Современный веб изобилует тяжелым контентом: дистрибутивы операционных систем, архивы с исходным кодом масштабных проектов и образы виртуальных машин легко могут превышать десятки гигабайт. Загрузка файлов такого объема через браузер всегда сопряжена с определенными рисками. Нестабильное соединение Wi-Fi, случайное закрытие вкладки, перезагрузка системы во время автоматического обновления или кратковременный срыв связи с сервером могут превратить часы ожидания в пустую трату времени, если браузер не поддерживает возобновление загрузки.

По умолчанию Mozilla Firefox отлично справляется с обработкой прерванных загрузок, но только в том случае, если удаленный сервер корректно настроен и поддерживает протокол HTTP/1.1 и выше. Однако на практике разработчики часто сталкиваются с ситуацией, когда Firefox по тем или иным причинам начинает загрузку файла с нулевой отметки заново, игнорируя уже скачанные гигабайты. В этой статье мы подробно разберем внутренние механизмы возобновления загрузок в Firefox, требования к серверной части, способы принудительной докачки через встроенные инструменты разработчика, а также программные методы контроля загрузочного потока с помощью JavaScript и современных API.

Анатомия прерванной загрузки: как Firefox работает с HTTP-диапазонами

Чтобы понять, почему одни файлы успешно докачиваются после обрыва связи, а другие скачиваются заново, необходимо обратиться к спецификации протокола HTTP. Ключевым элементом здесь является заголовок Range.

Когда Firefox инициирует запрос на скачивание файла, он отправляет стандартный GET-запрос. Если соединение прерывается, а браузер сохраняет временный файл (обычно с расширением .part) в директории загрузок, при попытке возобновить процесс Firefox отправляет повторный запрос с добавлением специального заголовка:

GET /downloads/huge-iso-file.iso HTTP/1.1
Host: example.com
Range: bytes=104857600-
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0

В ответ на такой запрос сервер, поддерживающий докачку, должен вернуть статус 206 Partial Content вместо стандартного 200 OK, а также заголовок Content-Range, подтверждающий с какого байта начата передача и каков общий размер файла:

HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Range: bytes 104857600-5368709119/5368709120
Content-Length: 5263851520
Content-Type: application/octet-stream

Если сервер возвращает статус 200 OK и начинает передачу файла с самого начала, Firefox автоматически аннулирует временный файл или начинает перезаписывать его, что фактически лишает пользователя возможности возобновить процесс без потери прогресса.

Но мало просто знать устройство запросов — чтобы клиентский браузер вообще получил шанс на спасительный 206 Partial Content (и не пришлось идти плакаться на Stack Overflow), всю эту машинерию необходимо правильно подготовить на бэкенде.

Настройка серверной стороны для поддержки возобновляемых загрузок

Обеспечение надежности загрузок на стороне клиента напрямую зависит от конфигурации веб-сервера. Рассмотрим базовые настройки для популярных решений.

Конфигурация Nginx

По умолчанию Nginx поддерживает диапазоны байтов для статических файлов автоматически благодаря модулю ngx_http_static_module. Однако при работе с проксированием (например, через proxy_pass) или кастомными бэкендами поведение нужно контролировать:

location /downloads/ {
    root /var/www;
    aio on;
    output_buffers 1 32k;
    sendfile_max_chunk 512k;
}

Конфигурация Apache

В Apache