Что делает менеджер загрузок, чего не сделает браузер
Файл на четыре гигабайта, готов на девяносто процентов — и тут звонок или просто заблокированный экран, и всё пропало. Это самая частая жалоба на загрузки в iOS, и это не баг. Операционная система делает ровно то, для чего была спроектирована, и именно поэтому существует отдельный класс приложений.
- 30 с Примерно столько работает приостановленное приложение, прежде чем iOS его остановит
- 206 HTTP-статус, который вообще делает докачку возможной
- 1 байт Столько данных перекачивается заново при правильно возобновлённой передаче
Почему передача останавливается при переключении приложений
iOS не позволяет приложению продолжать работать просто потому, что ему так хочется. Как только ты выходишь из приложения, оно приостанавливается в течение секунд, а у приостановленного приложения нет процессорного времени, нет сетевых соединений и нет способа заметить, что его остановили. Всё, что оно держало в памяти, никуда не делось, но заморожено — а если системе нужна память, приложение попросту завершается без предупреждения.
Поэтому загрузка, идущая через обычное соединение внутри приложения, заканчивается в момент жеста возврата на главный экран. Некоторые приложения маскируют это, выпрашивая у системы несколько дополнительных секунд фонового времени, — вот почему загрузка иногда переживает переход в фон ровно настолько, чтобы ты не сразу заметил, что она остановилась.
Правильный ответ на эту проблему устроен принципиально иначе. iOS предоставляет сервис фоновой передачи: ты отдаёшь системе список адресов и путей назначения, а систему саму скачивает файлы — в своём собственном процессе, по своему собственному расписанию. Твоё приложение может быть приостановлено, завершено или вообще не запущено — передача продолжается, а приложение перезапускается в фоне, когда появляется, о чём сообщить. Это механизм, который стоит за каждой загрузкой, переживающей заблокированный экран, и использовать его — решение, которое приложение принимает заранее на уровне архитектуры, а не настройка, которую можно включить.
Четыре механизма, от которых зависит, переживёт ли загрузка сбой
- Range-запрос
- HTTP-запрос, который просит байты начиная с позиции 5 000 000, а не файл целиком. Если сервер отвечает
206 Partial Content, докачка с середины возможна; если отвечает200 OKи отдаёт файл с начала — нет, файл придётся забирать заново с нуля. - Параллельные соединения
- Разбиение одного файла на несколько диапазонов и их одновременное скачивание. Помогает это потому, что одно соединение часто ограничивается сервером или зависит от задержки в оба конца, а не потому, что твой интернет становится быстрее от большего числа открытых сокетов.
- Зафиксированное смещение
- Сколько данных файла надёжно записано на диск, в отличие от того, что ещё «в пути». Загрузка, которая возобновляется с последнего зафиксированного байта, работает правильно; та, что возобновляется с того места, которое она *думает*, что получила, создаёт повреждённый файл, который проявит себя только часы спустя.
- Фоновая сессия
- Описанная выше передача, которой управляет система. Она медленнее стартует, ей нельзя задать произвольную кастомную логику, и это единственное, что продолжает работать, когда приложение не работает.
Почему загрузка обрывается и как выглядит каждый случай
Почти все жалобы на «зависшую загрузку» сводятся к одному из этих пяти случаев, и их легко отличить друг от друга, как только знаешь, на что смотреть.
| Что ты видишь | Что происходит на самом деле | Что помогает |
|---|---|---|
| Останавливается в тот момент, когда выходишь из приложения | Передача шла внутри процесса приложения, а не в фоновой сессии. | Снаружи ничего не сделать — это вопрос архитектуры приложения. |
| Каждый раз начинается заново с 0% | Сервер игнорирует range-запросы, поэтому продолжить с середины невозможно. | Стабильное соединение или файл поменьше. Некоторые хостинги разрешают диапазоны только для подписанных ссылок. |
| Раз за разом обрывается через несколько минут | Срок действия ссылки истёк. Многие хостинги выдают адреса, действующие пять-десять минут. | Заново получи ссылку со страницы и начни сначала — старая уже никогда не заработает. |
| Быстро скачивается, но файл не открывается | На самом деле пришла HTML-страница с ошибкой или страница входа с именем видеофайла. | Проверь размер — «фильм» на 14 КБ это веб-страница. Изучи ссылку прежде, чем начинать загрузку. |
| Очень медленно при быстром соединении | Ограничение скорости на стороне сервера, действующее на каждое соединение отдельно. | Больше параллельных соединений, если сервер это позволяет. Если ограничение считается по IP-адресу, а не по сокету, ничего не поможет. |
Когда файла для загрузки вообще не существует
Значительная часть видео в интернете передаётся не в виде файла. Она передаётся как HLS — плейлист .m3u8, перечисляющий сотни маленьких сегментов по несколько секунд каждый, часто в нескольких уровнях качества, чтобы плеер мог переключаться по мере изменения твоего соединения. Единого адреса, где хранился бы фильм, не существует, потому что сам фильм существует только как последовательность.
Сохранить такой поток значит скачать каждый сегмент, а затем ремультиплексировать их: записать видео- и аудиопотоки в обычный контейнер MP4. Ничего не перекодируется заново, поэтому ничего не теряется, и это занимает секунды, а не время, равное длине фильма. В результате получается обычный файл, который играет где угодно.
Именно поэтому «скачать этот поток» заметно дольше стартует, чем скачивание файла: сначала нужно получить и разобрать плейлист, выбрать уровень качества, и только потом начинают поступать сегменты. И именно поэтому некоторые потоки вообще нельзя сохранить: если сегменты зашифрованы по схеме DRM, ключи намеренно недоступны, и ни один законопослушный инструмент этого не обойдёт.
Что отличает настоящий менеджер загрузок от кнопки «скачать»
Переживает закрытие приложения
Фоновые передачи, отданные системе, с передачей эстафеты, которая продолжается с того же зафиксированного байта, а не начинает файл заново.
Сообщает, что за ссылка, прежде чем ты начнёшь
Размер, тип и поддерживает ли сервер докачку — всё это можно узнать одним HEAD-запросом, и всё это полезно узнать до того, как ты потратишь четыре гигабайта трафика.
Ставит в очередь, а не заливает всё разом
Десять файлов одновременно медленнее, чем по три за раз, потому что каждому соединению достаётся меньшая доля, а сбои умножаются. Очередь с разумным лимитом одновременных загрузок заканчивается быстрее.
В итоге получается обычный файл
В папке, которую ты видишь, с понятным именем, который проигрывается чем угодно, а не блоб в базе данных, который открывает только это приложение.
Привычки, которые предотвращают большинство проблем с загрузками
- Начинай большие файлы по Wi-Fi и держи экран включённым первые несколько секунд
Передача эстафеты фоновой сессии происходит рано; после этого экран уже не имеет значения.
- Не ставь в очередь двадцать файлов сразу
Три-пять одновременных передач — оптимальный диапазон почти на любом соединении.
- Проверяй свободное место заранее, а не постфактум
Передача, заполняющая диск, обрывается на 98%, а iOS к тому моменту может уже вычистить твой кэш, пытаясь освободить место.
- Относись с подозрением к мгновенному «завершено»
Фильм, «скачавшийся» за две секунды — это страница с ошибкой. Посмотри на размер файла.
- Получай истёкшие ссылки заново со страницы источника
Повторные попытки с мёртвой подписанной ссылкой обречены на провал, сколько бы раз приложение их ни повторяло.
Чем это отличается на разных устройствах
Самая строгая среда: приостановка агрессивна, а места на диске мало. Фоновые сессии здесь не оптимизация, а единственное, что вообще работает.
Те же правила, но простора чуть больше — и единственное устройство iOS, где большая библиотека вполне разумно может оказаться на внешнем диске вместо встроенной памяти.
Приостановки вообще нет, поэтому долгие передачи ведут себя так же, как на любом настольном компьютере. Практический предел — сервер, а не операционная система.
Вопросы, которые из этого возникают
Больше соединений всегда значит быстрее загрузка?
Нет. Они помогают, когда сервер ограничивает скорость каждого отдельного соединения, а это встречается часто. Они ничего не дают, если ограничение упирается в твоё собственное соединение, и могут навредить, если хостинг считает сокеты по IP-адресу и начинает их отклонять. Полезный диапазон где-то от четырёх до восьми; тридцать уже контрпродуктивно.
Может ли загрузка продолжаться при заблокированном экране?
Да, если она была передана системному сервису фоновой передачи. Экран блокировки для этого сервиса не имеет значения — важно то, что приложение приостановлено, а весь смысл этого механизма в том, чтобы работа продолжалась несмотря на это.
Почему моя загрузка начинается заново вместо того, чтобы продолжиться?
Сервер не учёл range-запрос. Это видно по тому, что прогресс сбрасывается на ноль, а не продолжается с места остановки. Некоторые хостинги поддерживают диапазоны только для своих подписанных ссылок на скачивание, некоторые отключают их полностью, а некоторые учитывают их для маленьких файлов, но не для больших.
Конвертация потока в MP4 — это то же самое, что перекодирование?
Нет. Ремультиплексирование переносит существующие видео и звук в контейнер MP4 без изменений — без потерь и достаточно быстро, чтобы завершиться за секунды. Перекодирование заново строит изображение с другим кодеком и всегда теряет в качестве. Если сохранение двухчасового потока занимает два часа, значит что-то перекодируется там, где в этом не было нужды.
Как FoxDL загружает файлы
У движка два режима: внутрипроцессный, который работает быстро, пока приложение на экране, и системная фоновая сессия, которая подхватывает работу с того же байта, когда его нет.
- Параллельные фрагменты для одного файла записываются сразу в финальное место на диске, а не во временные части, которые потом нужно склеивать.
- Фоновые передачи продолжаются после того, как приложение сходит с экрана, и подхватывают с последнего зафиксированного смещения — а не с того байта, который приложение считало последним.
- Возобновление после обрыва, перезагрузки или принудительного закрытия, если сервер учитывает range-запросы. Если нет, FoxDL так и сообщает, а не зацикливается.
- Потоки HLS ремультиплексируются в MP4, поэтому в библиотеке оказывается обычный файл, а не папка с сегментами.
- Инспектор загрузки сообщает реальный размер, тип и поддержку докачки для ссылки ещё до старта.
- Всё попадает в обычную папку, которую видит приложение «Файлы».
Бесплатные лимиты различаются по платформам: на iPhone и iPad — небольшое число попыток, пополняемое коротким рекламным видео, которое ты запускаешь сам; на Mac, где рекламы вообще нет, — фиксированное дневное число. Pro снимает лимит на любом устройстве.
Частые вопросы
- Продолжаются ли загрузки, когда я выхожу из приложения?
- Может ли прерванная загрузка возобновиться с того же места?
- Может ли FoxDL скачать поток HLS (m3u8)?
- Почему моя загрузка медленная и можно ли её ускорить?
- Сколько загрузок доступно в бесплатной версии?
Читать дальше
Что должно произойти прежде, чем веб-страница отдаст тебе свой файл
Четыре способа, которыми страница доставляет видео, и почему только один из них — файл, который можно сохранить.
Где на самом деле хранятся твои файлы на iPhone и кто может их видеть
Песочница, куда на самом деле попадают загрузки и почему переименование файла ломает столько приложений.
Почему твой iPhone открывает один видеофайл и отказывается открывать следующий
Контейнеры, кодеки и три способа посмотреть файл, который iOS отказывается открывать.
Твоя библиотека — наконец в одном месте.
Бесплатная загрузка. Без аккаунта и регистрации — полный набор в бесплатной версии.