Заголовок диапазона HTTP - PullRequest
76 голосов
/ 21 июля 2010

Я читал http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 и пытается выяснить, как продолжить загрузку файла.

Например, предположим, что файл имеет длину 100 байт, а у меня есть все 100 байт. Однако я не знаю, какой должен быть ожидаемый размер файла, поэтому я запрашиваю файл и указываю заголовок Range, который выглядит так:

Range: bytes=100-

Это действительный запрос диапазона?

Ответы [ 4 ]

136 голосов
/ 11 сентября 2013

Как предложил Wrikken , это правильный запрос.Это также довольно часто, когда клиент запрашивает носитель или возобновляет загрузку.

Клиент часто проверяет, обрабатывает ли сервер другие запросы, кроме простого поиска ответа Accept-Ranges.Chrome всегда отправляет Range: bytes=0- с первым GET-запросом на видео, поэтому вы не можете его отклонить.

Всякий раз, когда клиент включает Range: в свой запрос, даже еслион искажен, он ожидает частичного ответа (206).При поиске вперед во время воспроизведения видео HTML5 браузер запрашивает только начальную точку.Например:

Range: bytes=3744-

Итак, чтобы клиент правильно воспроизводил видео, ваш сервер должен иметь возможность обрабатывать эти неполные запросы диапазона.

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

Сначала вы можете ответить с запрошенной отправной точкой, указанной в ответе, затем с общей длинойфайл минус один (запрошенный диапазон байтов индексируется нулем).Например:

Запрос:

GET /BigBuckBunny_320x180.mp4 
Range: bytes=100-

Ответ:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/64656927

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

Запрос:

GET /BigBuckBunny_320x180.mp4
Range: bytes=100-

Ответ:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/*

Советы:

Вы всегда должны отвечатьдлина контента включена в диапазон.Если диапазон завершен, с начала до конца, то длина содержимого - это просто разница:

Запрос: Диапазон: байты = 500-1000

Ответ: Диапазон содержимого: байты 500-1000/123456

Помните, что диапазон индексируется нулем, поэтому Range: bytes=0-999 фактически запрашивает 1000 байтов, а не 999, поэтому ответьте что-то вроде:

Content-Length: 1000
Content-Range: bytes 0-999/123456

Или:

Content-Length: 1000
Content-Range: bytes 0-999/*

Но, если возможно, избегайте последнего метода, потому что некоторые медиапроигрыватели пытаются определить длительность по размеру файла.Если ваш запрос касается медиа-контента, что является моей догадкой, то вы должны указать его продолжительность в ответе.Это делается в следующем формате:

X-Content-Duration: 63.23 

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

X-Content-Duration: 7200.00 

В некоторых типах мультимедиа, таких как webm, вы также должны указать тип контента, например:

Content-Type: video/webm 

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

X-Content-Duration постепенно сокращается в пользу Content-Duration, поэтому я бы добавил и это.Основной ответ на запрос «0-» будет включать, по крайней мере, следующее:

HTTP/1.1 206 Partial Content
Date: Sun, 08 May 2013 06:37:54 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 3980
Content-Range: bytes 0-3979/3980
Content-Type: video/webm
X-Content-Duration: 2054.53
Content-Duration: 2054.53

Еще один момент: Chrome всегда начинает свой первый видео-запрос со следующего:

Range: bytes=0-

Некоторые серверы отправляют обычный ответ 200 в качестве ответа, который он принимает (но с ограниченными параметрами воспроизведения), но вместо этого попробуйте отправить 206, чтобы показать, что ваш сервер обрабатывает диапазоны. RFC 2616 говорит, что допустимо игнорировать заголовки диапазона.

52 голосов
/ 22 июля 2010

Это синтаксически правильный запрос, но не выполнимый запрос.Если вы посмотрите дальше в этом разделе, то увидите:

Если синтаксически допустимый набор диапазонов байтов включает в себя хотя бы одну спецификацию диапазона байтов, чей первый байтовый столбец меньше текущей длинытело-сущность или, по крайней мере, одна спецификация суффикс-байтового диапазона с ненулевой длиной суффикса, тогда набор байтов-диапазонов является выполнимым.В противном случае набор байтов-диапазонов является неудовлетворительным. Если набор байтов-диапазонов является неудовлетворительным, сервер ДОЛЖЕН вернуть ответ со статусом 416 (Запрошенный диапазон не выполняется) .В противном случае серверу СЛЕДУЕТ возвращать ответ со статусом 206 (частичное содержимое), содержащий допустимые диапазоны тела объекта.

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

7 голосов
/ 16 января 2014

Вопреки ответу Марка Новаковского, который по какой-то причине был одобрен многими, да, это действительный и выполнимый запрос.

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

3 голосов
/ 14 января 2019

Для людей, которые натыкаются на ответ Виктора Стоддарда, приведенный выше в 2019 году, и обнадеживаются и не унывают, обратите внимание, что:

a) Поддержка X-Content-Duration была удалена в Firefox 41: https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/41#HTTP

b) Я думаю, что он поддерживается только в Firefox для аудио .ogg и видео .ogv, но не для любых других типов.

c) Я не вижу, чтобы это когда-либо поддерживалось ввсе в Chrome, но это может быть просто отсутствие исследований с моей стороны.Но его присутствие или отсутствие, по-видимому, никак не влияют на веб-видео или видео ogv на сегодняшний день в Chrome 71.

d) Я не могу найти нигде, где «Длительность контента» заменила «Х-Content-Duration 'для чего-либо, я не думаю, что' X-Content-Duration 'жил достаточно долго, чтобы существовало имя заголовка преемника.

Я думаю, это означает, что на сегодняшний день, если вы хотитеобслуживайте контейнеры webm или ogv, которые содержат потоки, которые не знают своей продолжительности (например, вывод канала ffpeg), в Chrome или FF, и вы хотите, чтобы их можно было очищать в видеоэлементе HTML 5, вам, вероятно, не повезло.Firefox 64.0 делает нерешительную попытку сделать их пригодными для очистки, независимо от того, обслуживаете ли вы их через запросы диапазона, но он запутывается и подбрасывает вращающееся колесо, пока поток не будет полностью загружен, если вы ищете в несколько раз больше, чем он считает целесообразным.Chrome даже не пытается, он просто не работает и не позволяет вам чистить, пока весь поток не закончится воспроизведение .

...