Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Что такое $_SERVER['HTTP_RANGE']?
 
 автор: tAleks   (11.06.2007 в 12:10)   письмо автору
 
 

Что такое $_SERVER['HTTP_RANGE']?

   
 
 автор: sim5   (11.06.2007 в 12:52)   письмо автору
 
   для: tAleks   (11.06.2007 в 12:10)
 

http://axofiber.no-ip.org/inside/active.site.htm

   
 
 автор: Trianon   (11.06.2007 в 13:52)   письмо автору
 
   для: 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: И главное - ссылку на эту тему Вам показали. Не могли Вы мимо нее пройти.

   
 
 автор: tAleks   (12.06.2007 в 10:33)   письмо автору
 
   для: 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; 

   
 
 автор: Trianon   (12.06.2007 в 15:10)   письмо автору
 
   для: 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; 
а если позиция конца не задана - - будет равна размеру файла. 

>} 
>


На самом деле - там даже несколько более сложная конструкция. :)
Но основа именно такая.
А что в этом поле у Вас?

   
 
 автор: tAleks   (12.06.2007 в 19:39)   письмо автору
 
   для: 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; 
    } 



Этот кусок кода, как я понимаю, отдает файл по частям. Но зачем? Разве нельзя просто сразу вывести весь остаток файла?



Остальное вроде все понятно.


> А что в этом поле у Вас?

У меня в этом поле еще ничего нет. Ведь, как я понимаю, значение помещаемое в эту переменную, отправляется прогой, которая пытается докачивать файл. А т.к. скрипт я еще не написал, и не тестировал... следовательно там ничего нет еще... :)

   
 
 автор: Trianon   (12.06.2007 в 22:25)   письмо автору
 
   для: 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(); ?> и поглядеть, какие параметры передаются серверу.... еще до того, как что-то писать....

   
 
 автор: tAleks   (13.06.2007 в 10:27)   письмо автору
 
   для: Trianon   (12.06.2007 в 22:25)
 

>Этот код стоит под условием if($arnge[1] != $size) и исполняется, когда запрошен участок, не являющийся хвостом файла

>>Но зачем? Разве нельзя просто сразу вывести весь остаток файла?

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

Каких функций?
А просто выдать зарошенную часть (не хвост), без цикла нельзя?


>>> А что в этом поле у Вас?
>>У меня в этом поле еще ничего нет. Ведь, как я понимаю, значение помещаемое в эту переменную, отправляется прогой, которая пытается докачивать файл. А т.к. скрипт я еще не написал, и не тестировал... следовательно там ничего нет еще... :)
>
>Ну можно же просто запустить <? phpinfo(); ?> и поглядеть, какие параметры передаются серверу.... еще до того, как что-то писать....

Пробовал, там нет HTTP_RANGE. Пробовал сделать echo $_SERVER['HTTP_RANGE']; говорит что пеерменная не определена.

   
 
 автор: Trianon   (13.06.2007 в 10:36)   письмо автору
 
   для: tAleks   (13.06.2007 в 10:27)
 

>>Этот код стоит под условием if($arnge[1] != $size) и исполняется, когда запрошен участок, не являющийся хвостом файла
>>>Но зачем? Разве нельзя просто сразу вывести весь остаток файла?
>>Нельзя. Остаток не запрашивали. Запрашивали либо головную часть либо середину.
>>Если можно выкинуть весь хвост - это делается вызовом двух функций.
>Каких функций?

две строки выше этого фрагмента. fseek, fpassthru. Сразу под условием.

>А просто выдать зарошенную часть (не хвост), без цикла нельзя?

А как?

К сожалению, у функции fpassthru нет параметра, который бы указывал сколько данных из файла перегонять наружу....

>>Ну можно же просто запустить <? phpinfo(); ?> и поглядеть, какие параметры передаются серверу.... еще до того, как что-то писать....
>
>Пробовал, там нет HTTP_RANGE. Пробовал сделать echo $_SERVER['HTTP_RANGE']; говорит что пеерменная не определена.

Так к скрипту-то надо обращаться из программы многопоточной закачки - вроде flashget.
Впрочем, вероятно запрос на закачку будет не первым....

   
 
 автор: tAleks   (13.06.2007 в 11:33)   письмо автору
 
   для: Trianon   (13.06.2007 в 10:36)
 

>>А просто выдать зарошенную часть (не хвост), без цикла нельзя?
>
>А как?

Ну прочитать сразу часть файла, и выдать ее. Например так:


$buffer = fread($handle, 500);
echo $buffer;


Ведь, как я понял, в вашем примере, в цикле, делается тоже самое, только запрошенная часть файла, выдается кусками по 16384 байта.

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

   
 
 автор: Trianon   (13.06.2007 в 01:22)   письмо автору
 
   для: 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 в корне меняется.
В этом случае второе (после минуса) число нужно воспринимать как количество байт хвостового фрагмента

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

   
 
 автор: tAleks   (13.06.2007 в 10:41)   письмо автору
 
   для: 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"? Так?

   
 
 автор: Trianon   (13.06.2007 в 11:04)   письмо автору
 
   для: tAleks   (13.06.2007 в 10:41)
 

>Привиедите пожалуйста пример строки, которая в орингинале лежит в $_SERVER['HTTP_RANGE']. Т.к. как я понимаю, то там лежит что то вроде: "что-то=500-900". Так?

Само поле заголовка может выглядеть так:
Range: bytes=2000-
с 2000 и до конца файла

Range: bytes=500-700
201 байт с 500 по 700

Range: bytes=-300
300 последних байт

Range: bytes=0-99
100 первых байт

или даже так
Range: bytes=2000-, 500-700, -300, 0-99
все четыре диапазона сразу.

В $_SERVER['HTTP_RANGE'] лежит значение поля. То есть строка, начинающаяся с bytes.
например,
bytes=2000-


Следует отметить, что согласно синтаксиса, в строке могут попадаться пробелы...


>Т.е. если в $_SERVER['HTTP_RANGE'] лежит строка: "что-то=-900", то нужно выдать последине 900 байт файла?
>А если "что-то=0-900", то первые 900?
>Правильно понимаю?

именно так. Если вместо что-то поставить bytes - будет совсем правильно.


>>Кроме того, этот код неполон, поскольку не обрабатывает мультидиапазонные запросы - очень редкий тип запросов, при котором клиент требует от сервера сразу несколько фрагментов.
>Это когда $_SERVER['HTTP_RANGE'] = "bytes=500-700,601-999"? Так?
Да.

   
 
 автор: tAleks   (13.06.2007 в 11:38)   письмо автору
 
   для: Trianon   (13.06.2007 в 11:04)
 

>Следует отметить, что согласно синтаксиса, в строке могут попадаться пробелы...

А где эти пробелы могут быть? В любом месте? Тогда как правильно обработать эту строку и выбрать то, что нужно?


>>>Кроме того, этот код неполон, поскольку не обрабатывает мультидиапазонные запросы - очень редкий тип запросов, при котором клиент требует от сервера сразу несколько фрагментов.
>>Это когда $_SERVER['HTTP_RANGE'] = "bytes=500-700,601-999"? Так?
>Да.

А не могли бы вы дать небольой примерчик, по выдачи нескольких частей, при таком запросе? Хотя бы чтобы суть понять.

   
 
 автор: Trianon   (13.06.2007 в 11:54)   письмо автору
 
   для: tAleks   (13.06.2007 в 11:38)
 

>А не могли бы вы дать небольой примерчик, по выдачи нескольких частей, при таком запросе?
>Хотя бы чтобы суть понять.

Гы. Нет :)
Не надо прибедняться. Суть Вы уже поняли более чем капитально.
сиюминутной практической ценности для Вас этот пример не представляет, поскольку клиенты, проявляющие всё многообразие фантазии в рамках этого RFC - мне, например, просто не попадались. Полагаю, их вообще нет. Не каждый решится делать клиента, чтобы в самый разгар обмена данными получить в ответ весь файл ... или еще того хуже - статус 501 HTTP/1.1 Not implemented .

С долгоиграющей практической ценностью как поступать - Вы тоже знаете.

А я, если у cheops'а возникнет дефицит задач, предложу этот пример как очередную задачу.

   
 
 автор: tAleks   (13.06.2007 в 12:04)   письмо автору
 
   для: Trianon   (13.06.2007 в 11:54)
 

>Не надо прибедняться. Суть Вы уже поняли более чем капитально.

Как выдавать один запрощенный кусок - да. Понял.

А как выдавать 2 куска? В скрипте я вырезаю 2 куска, получаю их в переемнные: $part1 и $part2

Как их выдавать-то? Просто последовательно один за другим?

echo $part1;
echo $part2;


Или нужно какими-нибудь отедльными потоками параллельно? Ведь например когда я качаю файл ГетРайтом, он разибвает его на части все части качает одновременно. Вот этого я еще не понял, как реализовать.

   
 
 автор: Trianon   (13.06.2007 в 12:11)   письмо автору
 
   для: tAleks   (13.06.2007 в 12:04)
 

>Или нужно какими-нибудь отедльными потоками параллельно? Ведь например когда я качаю файл ГетРайтом, он разибвает его на части все части качает одновременно. Вот этого я еще не понял, как реализовать.

Он выдает два запроса параллельно и независимо. Каждый из запросов - простой фрагмент.

Первый (который начальную часть тянет) - возможно даже вообще нефрагментный, а обычный чистый GET

   
 
 автор: tAleks   (13.06.2007 в 12:21)   письмо автору
 
   для: Trianon   (13.06.2007 в 12:11)
 

>Он выдает два запроса параллельно и независимо. Каждый из запросов - простой фрагмент.

Т.е. когда ГетРайт разибвает на частьи файл, он делает несколько запросов. Т.е. за место одного такого:

"bytes=500-700,601-999"


Он делает два таких:

"bytes=500-700"
и
"bytes=601-999"


Так?

А такой запрос тогда, в каких случаях прменяется?

"bytes=500-700,601-999"


И как обрабатывается? Т.е. как выдать-то эти две части?

   
 
 автор: Trianon   (13.06.2007 в 12:42)   письмо автору
 
   для: 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-
закачав их - отправляет браузеру всё вместе одним куском.
Ну или несколькими кусками, но все равно одним откликом.

   
 
 автор: Trianon   (13.06.2007 в 12:16)   письмо автору
 
   для: tAleks   (13.06.2007 в 12:04)
 

С практической точки зрения, Вам не в эти дебри теперь лезть надо.
Вам нужно реализовывать логику запроса HEAD и условных запросов
IF-modified-since
IF-unmodified-since
If-match
If-range
Без этого нормальное клиент-серверное взаимодействие на практике обеспечить сложно.
Особенно, если файлы у Вас могут меняться время от времени....
а также (если требуется защищенная загрузка) логику проверки кукисов....

   
 
 автор: tAleks   (13.06.2007 в 12:37)   письмо автору
 
   для: Trianon   (13.06.2007 в 12:16)
 

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

Так, вроде бы работает. Но ГетРайт оказался качать через этот скрипт....

Как выяснилось позже... отказ произошел, потому что в начале скрипта стоит функция контроля авторизации. Без нее качает...

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования