У меня очень странная проблема с моим сценарием загрузки
это в основном
1.get id файла с методом «GET»
2.записывает имя и расположение этого файла из базы данных
3. передает его клиенту с заголовками и файлом чтения
но странно, что файл всегда выдается как поврежденный или поврежденный
например, если размер файла zip или rar прав, и он открывается нормально
но я не могу открыть сжатые файлы внутри него, и тогда я получаю поврежденную файлом ошибку
что странно, если бы у кода возникла проблема, я даже не смог бы открыть zip-файл (или, по крайней мере, я думаю, что не должен)
Другое дело, что я распечатал файл с его дорогой прямо перед отправкой заголовков, чтобы убедиться, что все в порядке.
я поместил адрес файла на url и загрузил файл, файл был в порядке без ошибок
так что все нормально, прежде чем отправлять заголовки
вот мой код
$file_id = isset($_GET['id']) && (int)$_GET['id'] != 0 ? (int)$_GET['id'] : exit; //////// finging file info $file = comon::get_all_by_condition('files' , 'id' , $file_id ); if(!$file) exit; foreach($file as $file){ $location = $file['location']; $filename = $file['file_name']; } ///////////// $site = comon::get_site_domian(); $ext = trim(end(explode('.' , $filename ))); $abslout_path = 'http://'.$site.'/'.$location.'/'.$filename; $relative = $location.'/'.$filename; ////////////////// content type switch($ext) { case 'txt': $cType = 'text/plain'; break; case 'pdf': $cType = 'application/pdf'; break; case 'zip': $cType = 'application/zip'; break; case 'doc': $cType = 'application/msword'; break; case 'xls': $cType = 'application/vnd.ms-excel'; break; case 'ppt': $cType = 'application/vnd.ms-powerpoint'; break; case 'gif': $cType = 'image/gif'; break; case 'png': $cType = 'image/png'; break; case 'jpeg': case 'jpg': $cType = 'image/jpg'; break; default: $cType = 'application/force-download'; break; } //////////////// just checking if(!file_exists($relative)){ echo $relative; echo '<br />'; exit; } if( !is_readable( $relative ) ) exit('its not redable'); if( headers_sent() ) exit('headers ? already sent !! '); header( 'Pragma: public' ); header( 'Expires: 0' ); header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' ); header( 'Cache-Control: private', false ); // required for certain browsers header( 'Content-Description:File Transfer' ); header($_SERVER['SERVER_PROTOCOL'].' 200 OK'); header( 'Content-Type:'.$cType); header( 'Content-Disposition: attachment; filename="'. basename($filename) . '";' ); header( 'Content-Transfer-Encoding: binary' ); header( 'Content-Length: ' . filesize($relative) ); readfile($abslout_path); exit;
Я проверил пару раз пару раз, и они прекрасны (я думаю), я также добавляю все заголовки, известные человеку, чтобы быть уверенным!
Я начинаю думать, может быть, это нечто иное, чем скрипт, например, кодировка символов или разрешение на папку! или что-то типа того !!
я что-то упускаю ?
Кажется, что он содержит код, который просто принудительно загружает, вот хорошая функция, которую я использую все время. Он будет обрабатывать файлы более 2 ГБ тоже.
<?php $file_id = (isset($_GET['id']) && (int)$_GET['id'] != 0) ? (int)$_GET['id'] : exit; /*finding file info*/ $file = comon::get_all_by_condition('files', 'id', $file_id); $path = $file['location'] . '/' . $file['file_name']; if (!is_file($path)) { echo 'File not found.('.$path.')'; } elseif (is_dir($path)) { echo 'Cannot download folder.'; } else { send_download($path); } return; //The function with example headers function send_download($file) { $basename = basename($file); $length = sprintf("%u", filesize($file)); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . $basename . '"'); header('Content-Transfer-Encoding: binary'); header('Connection: Keep-Alive'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . $length); set_time_limit(0); readfile($file); } ?>
В вашем сценарии может быть указано NOTICE или WARNING, попробуйте отключить отчет об ошибках поверх вашего скрипта:
error_reporting(0);
Очень приятно, полезно также …
но в вашем коде есть проблема –
header('Content-Disposition: attachment; filename="'.basename($file).'"';
пожалуйста, измените его следующим образом:
header('Content-Disposition: attachment; filename="'.basename($file).'"');
вы забыли закрыть его.
if (file_exists($file)) { set_time_limit(0); header('Connection: Keep-Alive'); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file).'"'); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file)); ob_clean(); flush(); readfile($file); }
Убедитесь, что у вас нет кода, выполненного после последнего readfile(FILE_NAME)
Мне пришлось добавить die();
или exit();
как последняя строка, поскольку среда MVC продолжает отображать представление после readfile