Заголовок Content-Length и chunked-кодировка - PullRequest
31 голосов
/ 10 марта 2010

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

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

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

Ответы [ 3 ]

31 голосов
/ 10 марта 2010

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

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

Также рассмотрите возможность добавления поддержки частичного контента / обслуживание в байтовом диапазоне - то есть возможность перезапустить загрузки. См. Здесь пример байтового диапазона (пример на PHP, но применим на любом языке). При подаче частичного контента вам нужна длина контента.

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

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

12 голосов
/ 10 марта 2010

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

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

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

5 голосов
/ 11 декабря 2017

Content-Length

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

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

Transfer-Encoding

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

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

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

Content-Encoding

Также возможно сжимать фрагментированные или не фрагментированные данные. Это практически делается через заголовок 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 vs Store & Forward

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...