Если на странице сайта сделать ссылку для скачивания файла <a href="имя файла">скачать</a>, то иногда начинается не закачка файла, а вывод содержимого файла пряма в браузер, подскажите, плиз как это делается с помощь заголовков, я так понимаю должна быть ссылка на страницу: <a href="имя страницы">скачать</a> на ней находятся заголовки: Content-Type: application/что-то здесь еще заголовки, напишите пожалуйста как это реализовать, к примеру файл с расширение *.rar
хорошо, но ведь нужно еще передать имя файла, потом Opera на этот заголовок окно загрузки файла не показывает, Прочитал имя файла можно указать: Content-Desposition: filename='имя файла', но работает только в mozilla
Ага как раз то, спасибо Только вместо Content-Type: application/octet-stream нужно указывать реальный mime тип, который можно определить к примеру firefox-ом для rar - application/x-rar-compressed
Вот в итоге PHP: // +-------------------------------------------------------------------------------------------+ // | Блок для закачки с сервера | // +-------------------------------------------------------------------------------------------+ if(isset($_GET['filename'])) { if (!file_exists($filename = $_GET['filename'])){ print "Файл " . $filename . "не найден!\r\n"; } else { set_time_limit(0); header('HTTP/1.0 200 OK'); header('Content-Disposition: attachment; filename="' . basename($filename) . '"'); header('Content-Transfer-Encoding: binary'); header('Accept-Ranges: bytes'); header('Content-Length: ' . (filesize($filename))); header('Content-Type: application/x-rar-compressed'); @readfile($filename); } } // +-------------------------------------------------------------------------------------------+ HTML: <a href="путь к странице с сценарием?filename=путь к файлу">Скачать</a>
dimalogin, не делай readfile(), делай как у меня частями. В моей версии хостер гораздо позже напишет, что ты убиваешь его любимый апачег.
а теперь и функция PHP: <?php /** * Функция для скачивания файла с сервера с возможностью докачки, * требует предварительной установки ограничения времени выполнения сценария * * @param string $realFilePath * @return bool */ function downloadFile($realFilePath) { // вначале проверим, что файл существует if(!file_exists($realFilePath)) { return false; } // соберем необходимую информацию о файле $CLen = filesize($realFilePath); $filename = basename($realFilePath); // запрашиваемое имя $file_extension = strtolower(substr(strrchr($filename, '.'), 1)); // Краткий перечень mime-типов $fileCType = 'application/octet-stream'; $CTypes = array ( 'pdf' => 'application/pdf', 'exe' => 'application/octet-stream', 'zip' => 'application/x-zip-compressed', 'rar' => 'application/x-rar-compressed', 'doc' => 'application/msword', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', 'gif' => 'image/gif', 'png' => 'image/png', 'jpe' => 'jpeg', 'jpg' => 'image/jpg' ); // Если расширение есть в перечне, присвоим соответствующий mime тип, // иначе остается общий if(isset($CTypes[$file_extension])) { $fileCType = $CTypes[$file_extension]; } // Формируем HTTP-заголовки ответа // $_SERVER['HTTP_RANGE'] — номер байта, c которого надо возобновить передачу содержимого файла. // проверим, что заголовок Range: bytes=range- был послан браузером или менеджером закачек if(isset($_SERVER['HTTP_RANGE'])) { $matches = array(); if(preg_match('/bytes=(\d+)-/', $_SERVER['HTTP_RANGE'], $matches)) { $rangePosition = intval($matches[1]); $newCLen = $CLen - $rangePosition; header ( 'HTTP/1.1 206 Partial content', true, 200 ); header ( 'Status: 206 Partial content' ); // Last-Modified - Дата послднего изменения содержимого. Поле актуально только для // статических страниц. Apache заменяет это поле значением поля Date для динамически // генерируемых страниц, в том числе для страниц содержащих SSI. header ( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');// always modified // HTTP/1.1 // Cache-control: no-cache - Управление кэш. Значение no-cache определяет запрет кэш // данной страницы. Для версии протокола HTTP/1.0 действует "Pragma: no-cache". header ( 'Cache-Control: no-store, no-cache, must-revalidate '); header ( 'Cache-Control: post-check=0, pre-check=0', false); // HTTP/1.0 header ( 'Pragma: no-cache' ); header ( 'Accept-Ranges: bytes'); header ( 'Content-Range: bytes ' . $rangePosition . '-' . $CLen - 1 . '/' . $CLen); header ( 'Content-Length: ' . $newCLen ); header ( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header ( 'Content-Description: File Transfer' ); header ( 'Content-Type: ' . $fileCType ); header ( 'Content-Transfer-Encoding: binary'); } else { return false; } } else { header ( 'HTTP/1.1 200 OK', true, 200 ); header ( 'Status: 200 OK' ); // Last-Modified - Дата послднего изменения содержимого. Поле актуально только для // статических страниц. Apache заменяет это поле значением поля Date для динамически // генерируемых страниц, в том числе для страниц содержащих SSI. header ( 'Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');// always modified // HTTP/1.1 // Cache-control: no-cache - Управление кэш. Значение no-cache определяет запрет кэш // данной страницы. Для версии протокола HTTP/1.0 действует "Pragma: no-cache". header ( 'Cache-Control: no-store, no-cache, must-revalidate '); header ( 'Cache-Control: post-check=0, pre-check=0', false); // HTTP/1.0 header ( 'Pragma: no-cache' ); header ( 'Accept-Ranges: bytes'); header ( 'Content-Length: ' . $CLen ); header ( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header ( 'Content-Description: File Transfer' ); header ( 'Content-Type: ' . $fileCType ); header ( 'Content-Transfer-Encoding: binary'); $rangePosition = 0; } // теперь необходимо встать на позицию $rangePosition и выдать в поток содержимое файла $handle = @fopen($realFilePath, 'rb'); if ($handle) { fseek($handle, $rangePosition); while(!feof($handle) and !connection_status()) { print fread($handle, (1024 * 8)); } return true; } else { return false; } } ?>
Моя функция скачивания файла работает но приписывает к файлу почему то текст HTML страницы с которой он скачивается Что я мог упустить? функция не эта. Если надо могу привести код. Если mp3 или jpg этого "не замечают" , то zip i rar это понимают с трудом, иногда совсем не понимают.
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 после вызова функции не помогает.
упс у меня ядро сервиса выводит заголовки автоматически вместе с фреймом (язык, стили) придется переписывать спасибо, я как то забыл про это
@Kviva @qtix привет некрофилам. На дворе 2020 год. Уважающие себя веб-серверы и реверс-прокси умеют в заголовок x-accel-redirect или его аналог. Поэтому примерно 69% опубликованного в этом треде объема сценариев избыточны, бессмысленны, а в кривых руках ещё и головную боль несут вместо пользы.
@Ganzal, последний – вообще подозрительный тип (бот): скопировал пост #3 и впер свою ссылку. Наверное, нужно банить