|
|
|
| Что такое $_SERVER['HTTP_RANGE']? | |
|
|
| |
|
|
|
|
для: sim5
(11.06.2007 в 12:52)
| | плохой пример. Не удовлетворяент семантике заголовка Range. Не учитывает границы конца диапазона.
в теме http://softtime.ru/forum/read.php?id_forum=1&id_theme=37589 приводился и полный пример (21.05.2007 в 14:43) , и описание самого заголовка (17.05.2007 в 14:37), и ссылки на рус, англ мануал по протоколу http. (там же)
to tAleks: И главное - ссылку на эту тему Вам показали. Не могли Вы мимо нее пройти. | |
|
|
|
|
|
|
|
для: Trianon
(11.06.2007 в 13:52)
| | Читал я эту тему, но в ней мне не все понято.
И к тому же к приведенном там примеру, коментарий, не гарантирующий работоспособность примера:
Честно скажу, написано только что, и на одном дыхании, так что корректность не проверял.
Но то, что вспомнил - учел.
Что конкретно содержит $_SERVER['HTTP_RANGE']? Хочется понять, почеу его надо
разбирать именно так:
if(isset($_SERVER['HTTP_RANGE']))
{
$range = explode('-', $_SERVER['HTTP_RANGE']);
if(!$range[0])$range[0] = 0;
if($range[1]) ++ $range[1];
else $range[1] = $size;
}
|
| |
|
|
|
|
|
|
|
для: tAleks
(12.06.2007 в 10:33)
| | >Читал я эту тему, но в ней мне не все понято.
Задавайте вопросы - по непонятным местам. Я отвечу.
>И к тому же к приведенном там примеру, коментарий, не гарантирующий работоспособность примера:
>Честно скажу, написано только что, и на одном дыхании, так что корректность не проверял.
>Но то, что вспомнил - учел.
Простите, это пример. Пример, показывающий, как можно разбирать запрос, а не код, отлаженный и вылизанный под ключ. Если Вам требуется именно такой - не вопрос: напишите мне личным сообщением - договоримся.
>Что конкретно содержит $_SERVER['HTTP_RANGE']?
И это было написано.
в этом поле указывается ПозицияНачала-ПозицияКонца
Позиция начала - это позиция первого байта, который нужно передать.
Позиция конца - это позиция последнего байта, который нужно передать.
пример: 5000-5999
получить пятую тысячу байт. Байты с позиции 5000 по позицию 5999
или пример: 20000-
Байты начиная с 20000 и до конца документа
или пример: -4095
Первые 4 килобайта документа
>Хочется понять, почеу его надо
>разбирать именно так:
>
>
Мне легче считать границы не с 5000 по 5999, а с 5000 и до 6000:
(и я сомневаюсь, что тот же код в исходной семантике можно записать проще)
>if(isset($_SERVER['HTTP_RANGE']))
>{
> $range = explode('-', $_SERVER['HTTP_RANGE']);
потому что позиции разделены знаком минус. И оба числа нужно извлечь.
> if(!$range[0])$range[0] = 0;
потому что если первая позиция не задана - нужно брать контент с нуля.
> if($range[1]) ++ $range[1];
потому что позиция следующего байта - перед которым остановиться - будет на единицу больше последнего нужного
> else $range[1] = $size;
а если позиция конца не задана - - будет равна размеру файла.
>}
>
|
На самом деле - там даже несколько более сложная конструкция. :)
Но основа именно такая.
А что в этом поле у Вас? | |
|
|
|
|
|
|
|
для: Trianon
(12.06.2007 в 15:10)
| | Спасибо за коментарии! Теперь начал что-то понимать.
Еще, пожалуйста прокоментируйте вот этот кусок:
for($blklen = 16384, $pos = $range_start; $pos < $range[1]; $pos += $buflen)
{
if($range[1]-$pos < $blklen)
$blklen = intval($range[1]-$pos);
$buffer = fread($handle, $blklen);
$buflen = strlen($buffer);
echo $buffer;
}
|
Этот кусок кода, как я понимаю, отдает файл по частям. Но зачем? Разве нельзя просто сразу вывести весь остаток файла?
Остальное вроде все понятно.
> А что в этом поле у Вас?
У меня в этом поле еще ничего нет. Ведь, как я понимаю, значение помещаемое в эту переменную, отправляется прогой, которая пытается докачивать файл. А т.к. скрипт я еще не написал, и не тестировал... следовательно там ничего нет еще... :) | |
|
|
|
|
|
|
|
для: tAleks
(12.06.2007 в 19:39)
| | >Спасибо за коментарии! Теперь начал что-то понимать.
>
>Еще, пожалуйста прокоментируйте вот этот кусок:
>
>for($blklen = 16384, $pos = $range_start; $pos < $range[1]; $pos += $buflen)
> {
> if($range[1]-$pos < $blklen)
> $blklen = intval($range[1]-$pos);
> $buffer = fread($handle, $blklen);
> $buflen = strlen($buffer);
> echo $buffer;
> }
>
|
>
>Этот кусок кода, как я понимаю, отдает файл по частям.
Этот код стоит под условием if($arnge[1] != $size) и исполняется, когда запрошен участок, не являющийся хвостом файла
>Но зачем? Разве нельзя просто сразу вывести весь остаток файла?
Нельзя. Остаток не запрашивали. Запрашивали либо головную часть либо середину.
Если можно выкинуть весь хвост - это делается вызовом двух функций.
>Остальное вроде все понятно.
Это радует.
>> А что в этом поле у Вас?
>У меня в этом поле еще ничего нет. Ведь, как я понимаю, значение помещаемое в эту переменную, отправляется прогой, которая пытается докачивать файл. А т.к. скрипт я еще не написал, и не тестировал... следовательно там ничего нет еще... :)
Ну можно же просто запустить <? phpinfo(); ?> и поглядеть, какие параметры передаются серверу.... еще до того, как что-то писать.... | |
|
|
|
|
|
|
|
для: Trianon
(12.06.2007 в 22:25)
| | >Этот код стоит под условием if($arnge[1] != $size) и исполняется, когда запрошен участок, не являющийся хвостом файла
>>Но зачем? Разве нельзя просто сразу вывести весь остаток файла?
>Нельзя. Остаток не запрашивали. Запрашивали либо головную часть либо середину.
>Если можно выкинуть весь хвост - это делается вызовом двух функций.
Каких функций?
А просто выдать зарошенную часть (не хвост), без цикла нельзя?
>>> А что в этом поле у Вас?
>>У меня в этом поле еще ничего нет. Ведь, как я понимаю, значение помещаемое в эту переменную, отправляется прогой, которая пытается докачивать файл. А т.к. скрипт я еще не написал, и не тестировал... следовательно там ничего нет еще... :)
>
>Ну можно же просто запустить <? phpinfo(); ?> и поглядеть, какие параметры передаются серверу.... еще до того, как что-то писать....
Пробовал, там нет HTTP_RANGE. Пробовал сделать echo $_SERVER['HTTP_RANGE']; говорит что пеерменная не определена. | |
|
|
|
|
|
|
|
для: tAleks
(13.06.2007 в 10:27)
| | >>Этот код стоит под условием if($arnge[1] != $size) и исполняется, когда запрошен участок, не являющийся хвостом файла
>>>Но зачем? Разве нельзя просто сразу вывести весь остаток файла?
>>Нельзя. Остаток не запрашивали. Запрашивали либо головную часть либо середину.
>>Если можно выкинуть весь хвост - это делается вызовом двух функций.
>Каких функций?
две строки выше этого фрагмента. fseek, fpassthru. Сразу под условием.
>А просто выдать зарошенную часть (не хвост), без цикла нельзя?
А как?
К сожалению, у функции fpassthru нет параметра, который бы указывал сколько данных из файла перегонять наружу....
>>Ну можно же просто запустить <? phpinfo(); ?> и поглядеть, какие параметры передаются серверу.... еще до того, как что-то писать....
>
>Пробовал, там нет HTTP_RANGE. Пробовал сделать echo $_SERVER['HTTP_RANGE']; говорит что пеерменная не определена.
Так к скрипту-то надо обращаться из программы многопоточной закачки - вроде flashget.
Впрочем, вероятно запрос на закачку будет не первым.... | |
|
|
|
|
|
|
|
для: Trianon
(13.06.2007 в 10:36)
| | >>А просто выдать зарошенную часть (не хвост), без цикла нельзя?
>
>А как?
Ну прочитать сразу часть файла, и выдать ее. Например так:
$buffer = fread($handle, 500);
echo $buffer;
|
Ведь, как я понял, в вашем примере, в цикле, делается тоже самое, только запрошенная часть файла, выдается кусками по 16384 байта.
Или может, это сделано для того чтобы большой файл в память не грузить целиком? | |
|
|
|
|
|
|
|
для: Trianon
(12.06.2007 в 15:10)
| | Похоже, я заработал себе довольно неприятную репутацию непререкаемого авторитета :(
Не в того - который ошибок не делает (таких, известное дело, нет) , а того, чьи ошибки не хотят замечать и подвергать критике.
>if(isset($_SERVER['HTTP_RANGE']))
>{
> $range = explode('-', $_SERVER['HTTP_RANGE']);
> потому что позиции разделены знаком минус. И оба числа нужно извлечь.
Эта строка склеилась из двух (поскольку тип диапазона нужно отрезать):
$range = explode('=', $_SERVER['HTTP_RANGE']);
$range = explode('-', $range[1]);
> if(!$range[0])$range[0] = 0;
потому что если первая позиция не задана - нужно брать контент с нуля.
Это утверждение неверно.
Если первая позиция не задана (не явно записана как ноль, а именно пропущена),
то семантика конструкции byte-range-spec в корне меняется.
В этом случае второе (после минуса) число нужно воспринимать как количество байт хвостового фрагмента
Кроме того, этот код неполон, поскольку не обрабатывает мультидиапазонные запросы - очень редкий тип запросов, при котором клиент требует от сервера сразу несколько фрагментов. | |
|
|
|
|
|
|
|
для: Trianon
(13.06.2007 в 01:22)
| | >>if(isset($_SERVER['HTTP_RANGE']))
>>{
>> $range = explode('-', $_SERVER['HTTP_RANGE']);
>> потому что позиции разделены знаком минус. И оба числа нужно извлечь.
>
>Эта строка склеилась из двух (поскольку тип диапазона нужно отрезать):
> $range = explode('=', $_SERVER['HTTP_RANGE']);
> $range = explode('-', $range[1]);
Привиедите пожалуйста пример строки, которая в орингинале лежит в $_SERVER['HTTP_RANGE']. Т.к. как я понимаю, то там лежит что то вроде: "что-то=500-900". Так?
>> if(!$range[0])$range[0] = 0;
>потому что если первая позиция не задана - нужно брать контент с нуля.
>Это утверждение неверно.
>Если первая позиция не задана (не явно записана как ноль, а именно пропущена),
>то семантика конструкции byte-range-spec в корне меняется.
>В этом случае второе (после минуса) число нужно воспринимать как количество байт хвостового фрагмента
Т.е. если в $_SERVER['HTTP_RANGE'] лежит строка: "что-то=-900", то нужно выдать последине 900 байт файла?
А если "что-то=0-900", то первые 900?
Правильно понимаю?
>
>Кроме того, этот код неполон, поскольку не обрабатывает мультидиапазонные запросы - очень редкий тип запросов, при котором клиент требует от сервера сразу несколько фрагментов.
Это когда $_SERVER['HTTP_RANGE'] = "bytes=500-700,601-999"? Так? | |
|
|
|
|
|
|
|
для: tAleks
(13.06.2007 в 10:41)
| | >Привиедите пожалуйста пример строки, которая в орингинале лежит в $_SERVER['HTTP_RANGE']. Т.к. как я понимаю, то там лежит что то вроде: "что-то=500-900". Так?
Само поле заголовка может выглядеть так: с 2000 и до конца файла
201 байт с 500 по 700
300 последних байт
100 первых байт
или даже так
Range: bytes=2000-, 500-700, -300, 0-99
| все четыре диапазона сразу.
В $_SERVER['HTTP_RANGE'] лежит значение поля. То есть строка, начинающаяся с bytes.
например,
Следует отметить, что согласно синтаксиса, в строке могут попадаться пробелы...
>Т.е. если в $_SERVER['HTTP_RANGE'] лежит строка: "что-то=-900", то нужно выдать последине 900 байт файла?
>А если "что-то=0-900", то первые 900?
>Правильно понимаю?
именно так. Если вместо что-то поставить bytes - будет совсем правильно.
>>Кроме того, этот код неполон, поскольку не обрабатывает мультидиапазонные запросы - очень редкий тип запросов, при котором клиент требует от сервера сразу несколько фрагментов.
>Это когда $_SERVER['HTTP_RANGE'] = "bytes=500-700,601-999"? Так?
Да. | |
|
|
|
|
|
|
|
для: Trianon
(13.06.2007 в 11:04)
| | >Следует отметить, что согласно синтаксиса, в строке могут попадаться пробелы...
А где эти пробелы могут быть? В любом месте? Тогда как правильно обработать эту строку и выбрать то, что нужно?
>>>Кроме того, этот код неполон, поскольку не обрабатывает мультидиапазонные запросы - очень редкий тип запросов, при котором клиент требует от сервера сразу несколько фрагментов.
>>Это когда $_SERVER['HTTP_RANGE'] = "bytes=500-700,601-999"? Так?
>Да.
А не могли бы вы дать небольой примерчик, по выдачи нескольких частей, при таком запросе? Хотя бы чтобы суть понять. | |
|
|
|
|
|
|
|
для: tAleks
(13.06.2007 в 11:38)
| | >А не могли бы вы дать небольой примерчик, по выдачи нескольких частей, при таком запросе?
>Хотя бы чтобы суть понять.
Гы. Нет :)
Не надо прибедняться. Суть Вы уже поняли более чем капитально.
сиюминутной практической ценности для Вас этот пример не представляет, поскольку клиенты, проявляющие всё многообразие фантазии в рамках этого RFC - мне, например, просто не попадались. Полагаю, их вообще нет. Не каждый решится делать клиента, чтобы в самый разгар обмена данными получить в ответ весь файл ... или еще того хуже - статус 501 HTTP/1.1 Not implemented .
С долгоиграющей практической ценностью как поступать - Вы тоже знаете.
А я, если у cheops'а возникнет дефицит задач, предложу этот пример как очередную задачу. | |
|
|
|
|
|
|
|
для: Trianon
(13.06.2007 в 11:54)
| | >Не надо прибедняться. Суть Вы уже поняли более чем капитально.
Как выдавать один запрощенный кусок - да. Понял.
А как выдавать 2 куска? В скрипте я вырезаю 2 куска, получаю их в переемнные: $part1 и $part2
Как их выдавать-то? Просто последовательно один за другим?
echo $part1;
echo $part2;
|
Или нужно какими-нибудь отедльными потоками параллельно? Ведь например когда я качаю файл ГетРайтом, он разибвает его на части все части качает одновременно. Вот этого я еще не понял, как реализовать. | |
|
|
|
|
|
|
|
для: tAleks
(13.06.2007 в 12:04)
| | >Или нужно какими-нибудь отедльными потоками параллельно? Ведь например когда я качаю файл ГетРайтом, он разибвает его на части все части качает одновременно. Вот этого я еще не понял, как реализовать.
Он выдает два запроса параллельно и независимо. Каждый из запросов - простой фрагмент.
Первый (который начальную часть тянет) - возможно даже вообще нефрагментный, а обычный чистый GET | |
|
|
|
|
|
|
|
для: Trianon
(13.06.2007 в 12:11)
| | >Он выдает два запроса параллельно и независимо. Каждый из запросов - простой фрагмент.
Т.е. когда ГетРайт разибвает на частьи файл, он делает несколько запросов. Т.е. за место одного такого:
Он делает два таких:
"bytes=500-700"
и
"bytes=601-999"
|
Так?
А такой запрос тогда, в каких случаях прменяется?
И как обрабатывается? Т.е. как выдать-то эти две части? | |
|
|
|
|
|
|
|
для: tAleks
(13.06.2007 в 12:21)
| | Допустим Вы закачиваете файл с сервера site.com через прокси-сервер proxy.com
Допустим, Ваш гетрайт (или как его) принимая 500 килобайтовый файл решил нашинковать канал запросами по 100 килобайт (для простоты пусть килобайт это 1000 байт)
Он выпустит запросы к proxy.com следующих диапазонов:
Range: bytes=0-
Range: bytes=100000-
Range: bytes=200000-
Range: bytes=300000-
Range: bytes=400000-
Прокси продубликует эти запросы серверу сайта.
Допустим также, что первый, третий и пятый запросы от прокси к серверу сайта по каким-то причинам отвалились, даже не начавшись.
Погоревав, Вы пришибли закачку . Прокси, пришиб выпущенные запросы, успев затянуть к себе вторую и четвертую часть.
Потом через часок Вы решаете попробовать затянуть файл снова - обычным браузером безо всякого гетрайта.
IE выдает GET в сторону прокси.
Прокси думает, вторая, четвертая части у меня уже закешированы. Надо бы раздобыть первую, третью, и пятую.
И запрашивает у site.com Range: bytes=0-99999,200000-299999,400000-
закачав их - отправляет браузеру всё вместе одним куском.
Ну или несколькими кусками, но все равно одним откликом. | |
|
|
|
|
|
|
|
для: tAleks
(13.06.2007 в 12:04)
| | С практической точки зрения, Вам не в эти дебри теперь лезть надо.
Вам нужно реализовывать логику запроса HEAD и условных запросов
IF-modified-since
IF-unmodified-since
If-match
If-range
Без этого нормальное клиент-серверное взаимодействие на практике обеспечить сложно.
Особенно, если файлы у Вас могут меняться время от времени....
а также (если требуется защищенная загрузка) логику проверки кукисов.... | |
|
|
|
|
|
|
|
для: Trianon
(13.06.2007 в 12:16)
| | По сути, мне надо просто разрешить скачивать несколько файлов, только авторизованным пользователям. Плюс еще хочется чтобы вся эта система поддерживала докачку. Вот и все, больших понтов не надо.
Так, вроде бы работает. Но ГетРайт оказался качать через этот скрипт....
Как выяснилось позже... отказ произошел, потому что в начале скрипта стоит функция контроля авторизации. Без нее качает... | |
|
|
|
|