За последние 24 часа нас посетили 22875 программистов и 1251 робот. Сейчас ищут 826 программистов ...

Как прикрутить скрипт отдачи файлов

Тема в разделе "PHP для новичков", создана пользователем Flint2010, 19 янв 2012.

  1. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    В общем по рекомендации создаю эту тему.
    Есть модуль для скачивания файлов с сайта.
    В файле модуля index.php, есть функция function view_file() функция формирует и показывает информацию об определенном файле, также в ней происходит действие на скачивание в форме
    Код (Text):
    1. <form method=\"POST\" action=\"modules.php?name=".$module_name."\">
    2.             <input type=\"hidden\" name=\"lid\" value=\"".$lid."\">
    3.             <input type=\"hidden\" name=\"path\" value=\"".$path."\">
    4.             <input type=\"hidden\" name=\"title\" value=\"".$title."\">
    5.             <input type=\"hidden\" name=\"file\" value=\"getit\">
    6.             <input type=\"submit\" value=\""._FILES_DOWNLFILE."\">
    7.          </form>
    Где
    $lid = id файла в БД
    $path = путь_к_файлу
    $title = Название файла под которым его увидит пользователь
    getit = getit.php (аналог download.php) где происходит непосредственно отдача файла
    В файл getit.php вставляю класс
    Код (Text):
    1. class download {
    2.  
    3. var $properties = array(
    4. 'old_name' => '',
    5. 'new_name' => '',
    6. 'type' => '',
    7. 'size' => '',
    8. 'resume' => '',
    9. 'max_speed' => ''
    10. );
    11.  
    12. var $range = 0;
    13.  
    14. function download($path, $name='', $type='application/force-download', $resume=0, $max_speed=0) {
    15.  
    16. $name = ($name == '') ? substr(strrchr("/".$path,"/"),1) : $name;
    17.  
    18. $file_size = @filesize($path);
    19.  
    20. $this->properties = array(
    21. 'old_name' => $path,
    22. 'new_name' => $name,
    23. 'type'=> $type,
    24. 'size' => $file_size,
    25. 'resume' => $resume,
    26. 'max_speed' => $max_speed
    27. );
    28.  
    29. if ($this->properties['resume']) {
    30.  
    31. if(isset($_SERVER['HTTP_RANGE'])) {
    32.  
    33. $this->range = $_SERVER['HTTP_RANGE'];
    34. $this->range = str_replace('bytes=', '', $this->range);
    35. $this->range = str_replace('-', '', $this->range);
    36.  
    37. } else {
    38.  
    39. $this->range = 0;
    40.  
    41. }
    42.  
    43. if ($this->range > $this->properties['size']) $this->range = 0;
    44.  
    45. } else {
    46.  
    47. $this->range = 0;
    48.  
    49. }
    50.  
    51. }
    52.  
    53.  
    54. function download_file() {
    55.  
    56. if ($this->range) {
    57. header($_SERVER['SERVER_PROTOCOL'].' 206 Partial Content');
    58. } else {
    59. header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
    60. }
    61. header('Pragma: public');
    62. header('Expires: 0');
    63. header('Cache-Control:');
    64. header('Cache-Control: public');
    65. header('Content-Description: File Transfer');
    66. header('Content-Type: '.$this->properties["type"]);
    67. header('Content-Disposition: attachment; filename="'.$this->properties['new_name'].'";');
    68. header('Content-Transfer-Encoding: binary');
    69.  
    70. if ($this->properties['resume']) header('Accept-Ranges: bytes');
    71.  
    72. if ($this->range) {
    73.  
    74. header("Content-Range: bytes {$this->range}-".($this->properties['size']-1)."/".$this->properties['size']);
    75. header("Content-Length: ".($this->properties['size']-$this->range));
    76.  
    77.  
    78. } else {
    79.  
    80. header("Content-Length: ".$this->properties['size']);
    81.  
    82. }
    83.  
    84. @ini_set('max_execution_time', 0);
    85. @set_time_limit();
    86. return $this->_download($this->properties['old_name'], $this->range);
    87. }
    88.  
    89. function _download ($filename, $range=0) {
    90. @ob_end_clean();
    91.  
    92. if (($speed = $this->properties['max_speed']) > 0)
    93. $sleep_time = (8 / $speed) * 1e6;
    94. else
    95. $sleep_time = 0;
    96.  
    97. $handle = fopen($filename, 'rb');
    98. fseek($handle,$range);
    99.  
    100. if ($handle === false) {
    101. return false;
    102. }
    103. //ob_flush();
    104. while (!feof($handle)) {
    105. print (fread($handle, 1024*8));
    106. flush();
    107. usleep($sleep_time);
    108. }
    109. fclose($handle);
    110. return true;
    111. }
    112. }
    113.  
    114. $a = new download($path, $title, 'application/force-download', true);
    В результате белая страница.
    Показ ошибок включен, в логах сервера ничего необычного.
     
  2. asokol

    asokol Активный пользователь

    С нами с:
    17 янв 2012
    Сообщения:
    162
    Симпатии:
    0
    Так конструктор download ничего не выводит, вот и пустая страница.
     
  3. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    ты еще одну строку забыл.
    $a->download_file();
     
  4. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Ой блин, точно. Спаисбо.Теперь файл пытается отдать, но при сохранении выдает ошибку
    Код (Text):
    1. Файл С:\TEMP\ddufisFD.mp3.part не может быть сохранен, так как исходный файл не может быть прочтен.
    2. Подождите некоторое время и попробуйте снова или обратитесь к администратору сервера.
    Вот такая фишка когда указан абсолютный путь к файлу. И вот такая ошибка когда указан относительный путь
    Код (Text):
    1. Warning: fopen(../../files/pub_dir/koroleva_vdohnoveniya_.mp3) [function.fopen]: failed to open stream: Нет такого файла или каталога in /home/moya_papka/modules/Files/getit.php on line 198
    Сами файлы находятся /home/moya_papka/files/pub_dir
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    смотри пути. может где-то что-то напутал
     
  6. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Да пути правильные, как я только их не пытался прописать. В конечном результате, абсолютный путь на 100% правильный. Кстати, а как fopen работает со слешами???
    Кстати положил файл непосредственно в modules/Files/
    и все равно Варнинг, вернее скачивается страница размером 4 Кб, ну а в исходнике страницы Варнинг
    И еще я не понял как может работать функция
    Код (Text):
    1. <?php
    2. function _download ($filename, $range=0) {
    3.             @ob_end_clean();
    4.  
    5.                 if (($speed = $this->properties['max_speed']) > 0) {
    6.                 $sleep_time = (8 / $speed) * 1e6;
    7.                     }else{
    8.                     $sleep_time = 0;
    9.                      }
    10.                     $handle = fopen($filename, 'rb');
    11.                     fseek($handle,$range);
    12.  
    13.                 if ($handle === false) {
    14.                 return false;
    15.                 }
    16.             //ob_flush();
    17.             while (!feof($handle)) {
    18.                 print (fread($handle, 1024*8));
    19.                 flush();
    20.                 usleep($sleep_time);
    21.             }
    22.             fclose($handle);
    23.             return true;
    24.             }
    Если переменно $filename нету при вызове
     
  7. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    странно.
    а что у тебя в пути?
    пропиши все один раз ручками без переменных, посмотри что получится.
     
  8. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    может раскомменить строку //ob_flush(); попробуй
     
  9. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    В общем дело немного сдвинулось, раскомментировал //ob_flush();, но работает только при указании абсолютного пути, при относительном не хочет.
    А вот теперь проблема файл скачивается на 97% и потом получаю затык на приблизительно на секунд 50, после чего загрузка завершается - это в Лисе
    В Опере - не определяется размер файла, время до окончания загрузки, количество скаченной информации. И в результате статус загрузки "Ошибка" хотя файл оказывается скаченным, также с затыком.
    Гугл хром. Также нету статуса файла времени и общего размера, а показывает только фактически загруженные Кб. В конце также 40 сек затык.
    В Эксплорере та же ситуация что и в хроме
     
  10. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    есть у меня мысль, что надо как-то послать недозабитый буфер. как - я не шарю =) надо спросить у гуру. у меня у самого тоже хоть файл и загружается, но все равно висит как бы закачка.
     
  11. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    А сюда гуру заглядывают?
    Вот вопросы подвисли в воздухе.
    1. Почему не передается весь размер файла браузеру?
    2. Почему на 97% подвисает загрузка до 1 минуты?
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    видимо сервер ждет от пхп ответа, пока он не отвалится =)

    а вот почему он не отваливается - нипанятна
     
  13. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    А почему размер браузеру не передается?
     
  14. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Кстати, как тут сделать проверку, что файл загружен полностью, чтобы увеличить счетчик?
    Код (Text):
    1. $db->sql_query("UPDATE ".$prefix."_files SET hits=hits+1 WHERE lid=".$lid);
     
  15. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    $a->download_file(); заменить на
    if ($a->download_file()) {
    успешно загружен
    }
     
  16. asokol

    asokol Активный пользователь

    С нами с:
    17 янв 2012
    Сообщения:
    162
    Симпатии:
    0
    Flint2010, лучше не использовать класс download в том виде, в котором он существует сейчас. Он содержит не менее 5 ошибок (которые видны на первый взгляд) - и синтаксические, и семантические, и логические. Попробуйте сначала исправить их, а потом уже двигаться дальше. Я укажу на пару из них:
    set_time_limit() - вызов без параметра.
    $this->range = str_replace('-', '', $this->range); - это будет работать только в одном случае, когда в HTTP_RANGE будет -[число], что означает последний блок из [число] байт. А как насчет того, что HTTP_RANGE может содержать [число]-[число]?
    К тому же код этот читаем, но с большим трудом. Я бы сказал, что он "некрасивый". Не в обиду будет сказано разработчику, как говорится: Москва не сразу строилась. :)
    Если мне и приходится спользовать чужой код, то сперва я разбираюсь, как это все работает, а потом его привожу к тому виду, который нравится мне . Речь, конечно же, не о целых движках. Да, и я не профессионал, учусь также как и Вы. Поэтому привыкайте сразу к чистому коду и кому будете помогать - тоже рекомендуйте это.
    Вот, приношу извинения за флуд.
     
  17. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    asokol У меня не столько опыта, чтобы чистить чужой код.
     
  18. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Неа, считает до загрузки файла
     
  19. asokol

    asokol Активный пользователь

    С нами с:
    17 янв 2012
    Сообщения:
    162
    Симпатии:
    0
    Тогда я больше не лезу.
     
  20. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    странно. возможно пхп отрабатывает и отдает это какомунть нгинксу и считает что отработал хорошо. хз как там.
     
  21. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    ага, у меня фронтедом nginx стоит
     
  22. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Ну почему же, если у вас есть практика, то можете подсказать.
     
  23. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    давайте доработаем и прикрепим новый вариант.
     
  24. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Я не против, но нужно чтобы опытные кодеры посоветовали и подсказали.
     
  25. Flint2010

    Flint2010 Активный пользователь

    С нами с:
    13 янв 2012
    Сообщения:
    22
    Симпатии:
    0
    Что так никто и не поможет?