Вопрос

Я пытаюсь взвесить все за и против установки Content-Length HTTP-заголовок вместо использования фрагментированного кодирования для возврата [возможно] больших файлов с моего сервера.Тот или иной вариант необходим для обеспечения совместимости со спецификациями HTTP 1.1 при использовании постоянных соединений.Я вижу преимущество Content-Length заголовок:

  • Диалоговые окна загрузки могут отображать точный индикатор выполнения.
  • Клиент заранее знает, может ли файл быть/не слишком большим для его проглатывания.

Обратной стороной является необходимость расчета размера перед возвратом объекта, что не всегда практично и может привести к увеличению использования сервера/базы данных.Недостатком фрагментированного кодирования являются небольшие накладные расходы на добавление размера фрагмента перед каждым фрагментом и индикатором выполнения загрузки.Есть предположения?Есть ли какие-нибудь другие соображения по HTTP для обоих методов, о которых я, возможно, не подумал?

Это было полезно?

Решение

Обязательно используйте Content-Length.Загрузка сервера при этом будет практически нулевой, а польза для ваших пользователей будет большой.

Для динамического контента также довольно просто добавить поддержку сжатых ответов (gzip).Для этого требуется буферизация вывода, что, в свою очередь, дает длину содержимого.(непрактично при загрузке файлов или уже сжатом контенте (звук, изображения)).

Рассмотрите также возможность добавления поддержки частичное содержаниеОбслуживание /byte-range — то есть возможность перезапустить загрузку. См. здесь пример диапазона байтов. (пример написан на PHP, но применим на любом языке).Вам понадобится Content-Length при подаче частичного контента.

Конечно, это не серебряные пули:для потоковой передачи мультимедиа бессмысленно использовать буферизацию вывода или размер ответа;для больших файлов буферизация вывода не имеет смысла, но Content-Length и обслуживание байтов имеют большой смысл (возможен перезапуск неудачной загрузки).

Лично я использую Content-Length всякий раз, когда знаю об этом;для загрузки файла проверка размера файла незначительна с точки зрения ресурсов.Результат:у пользователя есть определенный индикатор выполнения (и динамические страницы загружаются быстрее благодаря gzip).

Другие советы

Если длина контента известна заранее, я бы, конечно, предпочел ее отправке частями.Если в файловой системе локального диска или в базе данных есть статические файлы, то любой уважающий себя язык программирования и СУБД предоставляют способы заранее получить длину содержимого.Вам следует этим воспользоваться.

С другой стороны, если длина контента действительно заранее непредсказуема (например,если вы намерены объединить несколько файлов и отправить их как один), то отправка их частями может быть быстрее, чем буферизация в памяти сервера или первая запись в файловую систему локального диска.Но это действительно отрицательно влияет на пользовательский опыт, поскольку ход загрузки неизвестен.Нетерпеливые могут прервать загрузку и продолжить.

Еще одним преимуществом предварительного знания длины контента является возможность возобновить загрузку.В истории ваших сообщений я вижу, что ваш основной язык программирования — Java;ты можешь найти здесь статья с дополнительной технической информацией и примером Java-сервлета, который это делает.

Длина контента

А Content-Length Заголовок определяет длину тела запроса/ответа в байтах.Если вы не укажете Content-Length заголовок, HTTP-серверы неявно добавят Transfer-Encoding: chunked заголовок.А Content-Length и Transfer-Encoding заголовок не следует использовать вместе.Получатель понятия не имеет, какова длина тела сообщения, и не может оценить время завершения загрузки.Если вы добавите Content-Length заголовок, убедитесь, что он соответствует всему телу в байтах, если он неверен, поведение получателей не определено.

А Content-Length заголовок не допускает потоковую передачу, но он полезен для больших двоичных файлов, где вы хотите поддерживать частичную передачу контента.В основном это означает возобновляемые загрузки, приостановленные загрузки, частичные загрузки и многосетевые загрузки.Это требует использования дополнительного заголовка, называемого Range.Эта техника называется Обслуживание байтов.

Передача-кодирование

Использование Transfer-Encoding: chunked это то, что позволяет осуществлять потоковую передачу в рамках одного запроса или ответа.Это означает, что данные передаются по частям и не влияют на представление контента.

Официально HTTP-клиент предназначен для отправки запроса с TE Поле заголовка, указывающее, какие типы кодировок передачи готов принять клиент.Оно не всегда отправляется, однако большинство серверов предполагают, что клиенты могут обрабатывать chunked кодировки.

А chunked Кодирование передачи позволяет лучше использовать постоянные TCP-соединения, которые HTTP 1.1 считает истинными по умолчанию.

Кодирование контента

Также возможно сжимать фрагментированные или нефрагментированные данные.Практически это осуществляется через Content-Encoding заголовок.

Обратите внимание, что Content-Length равна длине тела после Content-Encoding.Это означает, что если вы заархивировали свой ответ, вычисление длины происходит после сжатия.Вам нужно будет иметь возможность загрузить все тело в память, если вы хотите вычислить длину (если у вас нет этой информации где-то еще).

При потоковой передаче с использованием фрагментированного кодирования алгоритм сжатия также должен поддерживать онлайн-обработку.К счастью, gzip поддерживает сжатие потоков.Я считаю, что контент сначала сжимается, а затем разбивается на куски.Таким образом, фрагменты принимаются, а затем распаковываются для получения реального контента.Если бы все было наоборот, вы получили бы сжатый поток, а затем распаковка дала бы нам фрагменты.Что не имеет смысла.

Типичный ответ сжатого потока может иметь следующие заголовки:

Content-Type: text/html
Content-Encoding: gzip
Transfer-Encoding: chunked

Семантически использование Content-Encoding указывает на «сквозную» схему кодирования, что означает, что только конечный клиент или конечный сервер должен декодировать контент.Прокси-серверы посередине не должны декодировать контент.

Если вы хотите разрешить прокси-серверам в середине декодировать контент, на самом деле правильным заголовком будет Transfer-Encoding заголовок.Если HTTP-запрос имел TE: gzip chunked заголовок, то можно ответить с помощью Transfer-Encoding: gzip chunked.

Однако это поддерживается очень редко.Поэтому вам следует использовать только Content-Encoding для вашего сжатия прямо сейчас.

Chunked против Store & Forward

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top