Заголовок диапазона HTTP

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

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

Range: bytes=100-

Является ли это допустимым запросом диапазона?

Ответ 1

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

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

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

Ответ 2

Как 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

Ответ:   Content-Range: байты 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 говорит, что допустимо игнорировать заголовки диапазонов.

Ответ 3

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

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