За последние 24 часа нас посетили 22039 программистов и 1672 робота. Сейчас ищут 1849 программистов ...

делаем ссылку для скачивания файла

Тема в разделе "Прочие вопросы по PHP", создана пользователем dimalogin, 16 ноя 2007.

  1. dimalogin

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

    С нами с:
    24 фев 2007
    Сообщения:
    27
    Симпатии:
    0
    Адрес:
    Москва
    Если на странице сайта сделать ссылку для скачивания файла
    <a href="имя файла">скачать</a>, то иногда начинается не закачка файла, а вывод содержимого файла пряма в браузер,
    подскажите, плиз как это делается с помощь заголовков, я так понимаю должна быть ссылка на страницу:
    <a href="имя страницы">скачать</a>
    на ней находятся заголовки:
    Content-Type: application/что-то
    здесь еще заголовки,
    напишите пожалуйста как это реализовать, к примеру файл с расширение *.rar
     
  2. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    Content-Type: application/octet-stream
     
  3. dimalogin

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

    С нами с:
    24 фев 2007
    Сообщения:
    27
    Симпатии:
    0
    Адрес:
    Москва
    хорошо, но ведь нужно еще передать имя файла, потом Opera на этот заголовок окно загрузки файла не показывает,
    Прочитал имя файла можно указать:
    Content-Desposition: filename='имя файла',
    но работает только в mozilla
     
  4. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
  5. dimalogin

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

    С нами с:
    24 фев 2007
    Сообщения:
    27
    Симпатии:
    0
    Адрес:
    Москва
    Ага как раз то, спасибо
    Только вместо Content-Type: application/octet-stream нужно указывать реальный mime тип, который можно определить к примеру firefox-ом
    для rar - application/x-rar-compressed
     
  6. Sergey89

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

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    application/octet-stream - это общий тип для бинарников.
     
  7. Anonymous

    Anonymous Guest

    есть еще

    application/force-download

    но не везде работает корректно...
     
  8. dimalogin

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

    С нами с:
    24 фев 2007
    Сообщения:
    27
    Симпатии:
    0
    Адрес:
    Москва
    Вот в итоге :)

    PHP:
    1.  
    2. // +-------------------------------------------------------------------------------------------+
    3. // | Блок для закачки с сервера                                                                        |
    4. // +-------------------------------------------------------------------------------------------+
    5. if(isset($_GET['filename'])) {
    6.     if (!file_exists($filename = $_GET['filename'])){
    7.         print "Файл " . $filename . "не найден!\r\n";
    8.     }
    9.     else {
    10.         set_time_limit(0);
    11.         header('HTTP/1.0 200 OK');
    12.         header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
    13.         header('Content-Transfer-Encoding: binary');
    14.         header('Accept-Ranges: bytes');
    15.         header('Content-Length: ' . (filesize($filename)));
    16.         header('Content-Type: application/x-rar-compressed');
    17.         @readfile($filename);
    18.     }
    19. }
    20. // +-------------------------------------------------------------------------------------------+
    21.  
    HTML:
    1.  
    2. <a href="путь к странице с сценарием?filename=путь к файлу">Скачать</a>
    3.  
     
  9. lexa

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

    С нами с:
    22 июл 2007
    Сообщения:
    1.746
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    dimalogin, не делай readfile(), делай как у меня частями. В моей версии хостер гораздо позже напишет, что ты убиваешь его любимый апачег.
     
  10. dimalogin

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

    С нами с:
    24 фев 2007
    Сообщения:
    27
    Симпатии:
    0
    Адрес:
    Москва
    а теперь и функция :)
    PHP:
    1.  
    2. <?php
    3. /**
    4.  * Функция для скачивания файла с сервера с возможностью докачки,
    5.  * требует предварительной установки ограничения времени выполнения сценария
    6.  *
    7.  * @param string $realFilePath
    8.  * @return bool
    9.  */
    10. function downloadFile($realFilePath) {
    11.     // вначале проверим, что файл существует
    12.     if(!file_exists($realFilePath)) {
    13.         return false;
    14.     }
    15.     // соберем необходимую информацию о файле
    16.     $CLen = filesize($realFilePath);
    17.     $filename = basename($realFilePath); // запрашиваемое имя
    18.     $file_extension = strtolower(substr(strrchr($filename, '.'), 1));
    19.     // Краткий перечень mime-типов
    20.     $fileCType = 'application/octet-stream';
    21.     $CTypes = array (
    22.     'pdf' => 'application/pdf',
    23.     'exe' => 'application/octet-stream',
    24.     'zip' => 'application/x-zip-compressed',
    25.     'rar' => 'application/x-rar-compressed',
    26.     'doc' => 'application/msword',
    27.     'xls' => 'application/vnd.ms-excel',
    28.     'ppt' => 'application/vnd.ms-powerpoint',
    29.     'gif' => 'image/gif',
    30.     'png' => 'image/png',
    31.     'jpe' => 'jpeg',
    32.     'jpg' => 'image/jpg'
    33.     );
    34.     // Если расширение есть в перечне, присвоим соответствующий mime тип,
    35.     // иначе остается общий
    36.     if(isset($CTypes[$file_extension])) {
    37.         $fileCType = $CTypes[$file_extension];
    38.     }
    39.     // Формируем HTTP-заголовки ответа
    40.     // $_SERVER['HTTP_RANGE'] — номер байта, c которого надо возобновить передачу содержимого файла.
    41.     // проверим, что заголовок Range: bytes=range- был послан браузером или менеджером закачек
    42.     if(isset($_SERVER['HTTP_RANGE'])) {
    43.         $matches = array();
    44.         if(preg_match('/bytes=(\d+)-/', $_SERVER['HTTP_RANGE'], $matches)) {
    45.             $rangePosition = intval($matches[1]);
    46.             $newCLen = $CLen - $rangePosition;
    47.             header ( 'HTTP/1.1 206 Partial content', true, 200 );
    48.             header ( 'Status: 206 Partial content' );
    49.             // Last-Modified - Дата послднего изменения содержимого. Поле актуально только для
    50.             // статических страниц. Apache заменяет это поле значением поля Date для динамически
    51.             // генерируемых страниц, в том числе для страниц содержащих SSI.
    52.             header ( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');// always modified
    53.             // HTTP/1.1
    54.             // Cache-control: no-cache - Управление кэш. Значение no-cache определяет запрет кэш
    55.             // данной страницы. Для версии протокола HTTP/1.0 действует "Pragma: no-cache".
    56.             header ( 'Cache-Control: no-store, no-cache, must-revalidate ');
    57.             header ( 'Cache-Control: post-check=0, pre-check=0', false);
    58.             // HTTP/1.0
    59.             header ( 'Pragma: no-cache' );
    60.             header ( 'Accept-Ranges: bytes');
    61.             header ( 'Content-Range: bytes ' . $rangePosition . '-' . $CLen - 1 . '/' . $CLen);
    62.             header ( 'Content-Length: ' . $newCLen );
    63.             header ( 'Content-Disposition: attachment; filename="' . $filename . '"' );
    64.             header ( 'Content-Description: File Transfer' );
    65.             header ( 'Content-Type: ' . $fileCType );
    66.             header ( 'Content-Transfer-Encoding: binary');
    67.         }
    68.         else {
    69.             return false;
    70.         }
    71.     }
    72.     else {
    73.         header ( 'HTTP/1.1 200 OK', true, 200 );
    74.         header ( 'Status: 200 OK' );
    75.         // Last-Modified - Дата послднего изменения содержимого. Поле актуально только для
    76.         // статических страниц. Apache заменяет это поле значением поля Date для динамически
    77.         // генерируемых страниц, в том числе для страниц содержащих SSI.
    78.         header ( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');// always modified
    79.         // HTTP/1.1
    80.         // Cache-control: no-cache - Управление кэш. Значение no-cache определяет запрет кэш
    81.         // данной страницы. Для версии протокола HTTP/1.0 действует "Pragma: no-cache".
    82.         header ( 'Cache-Control: no-store, no-cache, must-revalidate ');
    83.         header ( 'Cache-Control: post-check=0, pre-check=0', false);
    84.         // HTTP/1.0
    85.         header ( 'Pragma: no-cache' );
    86.         header ( 'Accept-Ranges: bytes');
    87.         header ( 'Content-Length: ' . $CLen );
    88.         header ( 'Content-Disposition: attachment; filename="' . $filename . '"' );
    89.         header ( 'Content-Description: File Transfer' );
    90.         header ( 'Content-Type: ' . $fileCType );
    91.         header ( 'Content-Transfer-Encoding: binary');
    92.         $rangePosition = 0;
    93.     }
    94.     // теперь необходимо встать на позицию $rangePosition и выдать в поток содержимое файла
    95.     $handle = @fopen($realFilePath, 'rb');
    96.     if ($handle) {
    97.         fseek($handle, $rangePosition);
    98.         while(!feof($handle) and !connection_status()) {
    99.             print fread($handle, (1024 * 8));
    100.         }
    101.         return true;
    102.     }
    103.     else {
    104.         return false;
    105.     }
    106. }
    107. ?>
    108.  
     
  11. Anonymous

    Anonymous Guest

    dimalogin, посмотри функцию mime_content_type()
     
  12. dj--alex

    dj--alex Активный пользователь

    С нами с:
    29 ноя 2007
    Сообщения:
    184
    Симпатии:
    0
    Моя функция скачивания файла работает но приписывает к файлу почему то текст HTML страницы с которой он скачивается
    Что я мог упустить? функция не эта.
    Если надо могу привести код.

    Если mp3 или jpg этого "не замечают" , то zip i rar это понимают с трудом, иногда совсем не понимают.
     
  13. Sergey89

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

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    мб exit забыт где и выводится не только файл но и весь дальнейший текст.
     
  14. dj--alex

    dj--alex Активный пользователь

    С нами с:
    29 ноя 2007
    Сообщения:
    184
    Симпатии:
    0
    function sendfile ($file) { //not tested
    $file_server_path = $file;
    $download_size = filesize( $file_server_path );
    //header("Content-type: application/x-download");
    header("Content-Disposition: attachment; filename=" . $file_server_path . ";");
    header("Content-Type: application/x-force-download; name=\"".$file_server_path."\"");
    header("Accept-Ranges: bytes");
    header("Content-Length: " . $download_size );
    readfile( $file_server_path );
    }

    плохо что такая скачка изменяет имя файла и добавляет текст в начало(!) файла.
    с концом как раз все в порядке. Вставка exit после вызова функции не помогает.
     
  15. Sergey89

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

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Дак вызывай функцию до вывода текста.
     
  16. dj--alex

    dj--alex Активный пользователь

    С нами с:
    29 ноя 2007
    Сообщения:
    184
    Симпатии:
    0
    упс у меня ядро сервиса выводит заголовки автоматически вместе с фреймом (язык, стили)
    придется переписывать спасибо, я как то забыл про это :)
     
  17. Kviva

    Kviva Новичок

    С нами с:
    26 мар 2020
    Сообщения:
    1
    Симпатии:
    0
    Здравствуйте.
    Почему у меня на сайте, при нажатии кнопки скачать, выходит только php скрипт?
     
  18. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    @Kviva @qtix привет некрофилам. На дворе 2020 год. Уважающие себя веб-серверы и реверс-прокси умеют в заголовок x-accel-redirect или его аналог. Поэтому примерно 69% опубликованного в этом треде объема сценариев избыточны, бессмысленны, а в кривых руках ещё и головную боль несут вместо пользы.
     
  19. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.840
    Симпатии:
    652
    @Ganzal, последний – вообще подозрительный тип (бот): скопировал пост #3 и впер свою ссылку. Наверное, нужно банить ;)