Я пытаюсь разрешить пользователю моего сайта загружать файлы. Более того, я хотел бы испечь это в структуре Front Controller, которую я создал / использую. Я могу получить загрузку, но при попытке открыть файл Adobe Reader всегда дает сообщение о том, что файл имеет неподдерживаемый тип или он поврежден. В разделе «Мои загрузки» говорится, что размер файла равен 0 КБ, что, очевидно, неверно, поэтому он становится поврежденным. Однако я не знаю, почему.
Я могу загрузить загрузку, но пропуская рамки Front Controller и просто запустив скрипт загрузки. Этот скрипт выглядит так и называется downloadManager.php и вызывается из ссылки с href = "/ myApp / downloads / downloadManager.php:
<?php header("Content-Type: application/octet-stream"); $file = "eZACKe_1359081853_Week Three Sprints & Hurdles Workout 24th - 28th of Sept (1).pdf"; header("Content-Disposition: attachment; filename=" . $file); header("Content-Type: application/octet-stream"); header("Content-Type: application/download"); header("Content-Description: File Transfer"); header("Content-Length: " . filesize($file)); flush(); // this doesn't really matter. $fp = fopen($file, "r"); while (!feof($fp)) { echo fread($fp, 65536); flush(); // this is essential for large downloads } fclose($fp); ?>
Это работает, но я бы хотел, чтобы мои рамки работали. Это поток кода, используя мою фреймворк, с ссылкой href, href = "/ myApp / downloadz? Type = 'resume' & id = '8'":
URL-адрес переписывается apache и переходит к index.php, который является моим передним контроллером:
<?php class Foo { static public function test($classname) { if(preg_match('/\\\\/', $classname)) { $path = str_replace('\\', '/', $classname); } else { $path = str_replace('_', '/', $classname); } if (is_readable($path.".php")) { require_once $path .".php"; } } } spl_autoload_register('\Foo::test'); \controller\Controller::run(); ?>
Что приводит к контроллеру:
static function run() { $instance = new Controller(); $instance->init(); $instance->handleRequest(); }
init устанавливает соединение PDO MySQL, а также загружает некоторые файлы конфигурации с помощью Simple_XML_Load
Затем,
function handleRequest() { $request = new \controller\Request(); $cmd_r = new \commands\common\CommandResolver(); $cmd = $cmd_r->getCommand($request); $presenter = $cmd->execute($request); if(!$request->getProperty('ajax') && !is_a($cmd, '\commands\Download\DownloadCommand')) { echo $this->handleRender($request, $presenter); } }
Единственное, что нужно отметить здесь – getCommand и проверяет, существуют ли файлы и использует отражение
Итак, вызывается $ cmd-> execute и на этом этапе мы вызываем DownloadzCommand :: execute,
function execute(\controller\Request $request) { parent::execute($request); if($this->request->getProperty("type") == "resume" || $this->request->getProperty("type") == "coverLetter") { $this->handleJobApplicationDownload(); } } private function handleJobApplicationDownload() { if(!$this->loggedInMember) { exit; } try { $idobj = new \mapper\IdentityObject (); $jobApplication = \domain\JobApplication::produceOne($idobj->field("jobApplication.jobApplicationId")->eq($this->request->getProperty("id"))->field("jobApplication.jobId")->eq("jobs.jobId", false)->field("businesses.businessId")->eq("jobs.businessId", false)->field("jobApplication.dateApplicationViewed")->isnull("", false), null, "JobBusinessJoin"); // get here the jobApplication is legit - now make sure the logged in member is a recruiter for this business $idobj = new \mapper\IdentityObject (); $business = \domain\Business::produceOne($idobj->field("businessId")->eq($jobApplication->getState("businessId"))); if(!$business->isRecruiter($this->loggedInMember->getId())) { exit; } else { if($this->request->getProperty("type") == "resume") { if($path = $jobApplication->getState("resumeUploadPath")) { // have a resume path, move it over $fullPath = "common/jobs/resumes/".$path; $tempDest = "commands/Downloadz/$path"; copy($fullPath, $tempDest); } else { exit; } } elseif($this->request->getProperty("type") == "coverLetter") { if($path = $jobApplication->getState("coverLetterUploadPath")) { // have a coverLetter path, move it over $fullPath = "common/jobs/coverLetters/".$path; } else { exit; } } } } catch(\base\ObjectDoesNotExistException $e) { echo "nope"; } header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=" . $path); header("Content-Type: application/octet-stream"); header("Content-Type: application/download"); header("Content-Description: File Transfer"); header("Content-Length: " . filesize($path)); flush(); // this doesn't really matter. $fp = fopen($file, "r"); while (!feof($fp)) { echo fread($fp, 65536); flush(); // this is essential for large downloads } fclose($fp); unlink($path); }
И в этот момент происходит загрузка. Однако я открываю файл, и он поврежден.
Заметка, то же самое происходит даже для простого текстового файла.
Кроме того, он также не работает, даже если я пропускаю часть копирования файлов и просто имею файл в командах / Downloadz.
Есть идеи?
Вместо того, чтобы использовать:
$fp = fopen($file, "r"); while (!feof($fp)) { echo fread($fp, 65536); flush(); // this is essential for large downloads } fclose($fp);
Использовать readfile()
readfile($file);
У меня была такая же проблема, но после чтения http://davidwalsh.name/php-force-download теперь работает.
header('Pragma: public'); // required header('Expires: 0'); // no cache header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: private', false); header('Content-Type: application/pdf'); header('Last-Modified: ' . gmdate('D, d MYH:i:s', filemtime($filepath)) . ' GMT'); header('Content-disposition: attachment; filename=' . $pathinfo['filename'] . '.pdf'); header("Content-Transfer-Encoding: binary"); header('Content-Length: ' . filesize($filepath)); // provide file size header('Connection: close'); readfile($filepath); exit();
Это работает для меня.