Я написал скрипт PHP, который обрабатывает загрузку файлов, определяет, какой файл запрашивается, и устанавливая правильные заголовки HTTP, чтобы заставить браузер фактически загружать файл (а не отображать его в браузере).
У меня теперь есть проблема, когда некоторые пользователи сообщают о некорректных идентификаторах определенных файлов (так что независимо от расширения браузер будет рассматривать это изображение GIF). Я предполагаю, что это потому, что я не задал «Content-type» в заголовке ответа. Скорее всего, это так? Если да, существует ли довольно общий тип, который можно было бы использовать для всех файлов, вместо того, чтобы пытаться учитывать все возможные типы файлов?
В настоящее время я устанавливаю значение «Content-disposition: attachment; filename = arandomf.ile»
Обновление: я последовал этому руководству здесь, чтобы создать более надежный процесс загрузки файлов ( http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/ ) , но существует значительная задержка между выполнением сценария и появлением диалогового окна загрузки браузера. Может ли кто-нибудь определить узкое место, которое вызывает это?
Вот моя реализация:
/** * Outputs the specified file to the browser. * * @param string $filePath the path to the file to output * @param string $fileName the name of the file * @param string $mimeType the type of file */ function outputFile($filePath, $fileName, $mimeType = '') { // Setup $mimeTypes = array( 'pdf' => 'application/pdf', 'txt' => 'text/plain', 'html' => 'text/html', 'exe' => 'application/octet-stream', 'zip' => 'application/zip', 'doc' => 'application/msword', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', 'gif' => 'image/gif', 'png' => 'image/png', 'jpeg' => 'image/jpg', 'jpg' => 'image/jpg', 'php' => 'text/plain' ); $fileSize = filesize($filePath); $fileName = rawurldecode($fileName); $fileExt = ''; // Determine MIME Type if($mimeType == '') { $fileExt = strtolower(substr(strrchr($filePath, '.'), 1)); if(array_key_exists($fileExt, $mimeTypes)) { $mimeType = $mimeTypes[$fileExt]; } else { $mimeType = 'application/force-download'; } } // Disable Output Buffering @ob_end_clean(); // IE Required if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } // Send Headers header('Content-Type: ' . $mimeType); header('Content-Disposition: attachment; filename="' . $fileName . '"'); header('Content-Transfer-Encoding: binary'); header('Accept-Ranges: bytes'); // Send Headers: Prevent Caching of File header('Cache-Control: private'); header('Pragma: private'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Multipart-Download and Download Resuming Support if(isset($_SERVER['HTTP_RANGE'])) { list($a, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); list($range) = explode(',', $range, 2); list($range, $rangeEnd) = explode('-', $range); $range = intval($range); if(!$rangeEnd) { $rangeEnd = $fileSize - 1; } else { $rangeEnd = intval($rangeEnd); } $newLength = $rangeEnd - $range + 1; // Send Headers header('HTTP/1.1 206 Partial Content'); header('Content-Length: ' . $newLength); header('Content-Range: bytes ' . $range - $rangeEnd / $size); } else { $newLength = $size; header('Content-Length: ' . $size); } // Output File $chunkSize = 1 * (1024*1024); $bytesSend = 0; if($file = fopen($filePath, 'r')) { if(isset($_SERVER['HTTP_RANGE'])) { fseek($file, $range); while(!feof($file) && !connection_aborted() && $bytesSend < $newLength) { $buffer = fread($file, $chunkSize); echo $buffer; flush(); $bytesSend += strlen($buffer); } fclose($file); } } }
В соответствии с RFC 2046 (Многоцелевые расширения электронной почты Интернета) :
Рекомендуемое действие для реализации, которое получает
Объект «application / octet-stream» должен просто предложить помещать данные в файл
Поэтому я поеду за этим.
Как объясняется ссылкой Алекса, вам, вероятно, не хватает заголовка Content-Disposition
поверх Content-Type
.
Так что-то вроде этого:
Content-Disposition: attachment; filename=MyFileName.ext
Вы можете попробовать этот сценарий загрузки Force-download . Даже если вы его не используете, это, вероятно, укажет вам в правильном направлении:
<?php $filename = $_GET['file']; // required for IE, otherwise Content-disposition is ignored if(ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off'); // addition by Jorg Weske $file_extension = strtolower(substr(strrchr($filename,"."),1)); if( $filename == "" ) { echo "<html><title>eLouai's Download Script</title><body>ERROR: download file NOT SPECIFIED. USE force-download.php?file=filepath</body></html>"; exit; } elseif ( ! file_exists( $filename ) ) { echo "<html><title>eLouai's Download Script</title><body>ERROR: File not found. USE force-download.php?file=filepath</body></html>"; exit; }; switch( $file_extension ) { case "pdf": $ctype="application/pdf"; break; case "exe": $ctype="application/octet-stream"; 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"; } header("Pragma: public"); // required 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-Type: $ctype"); // change, added quotes to allow spaces in filenames, by Rajkumar Singh header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" ); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".filesize($filename)); readfile("$filename"); exit();