File Handler возвращает искаженные файлы - PullRequest
0 голосов
/ 09 апреля 2010

В течение последних 3 месяцев мой сайт использовал обработчик файлов PHP в сочетании с htaccess. Пользователи, имеющие доступ к папке загрузки сайта, будут перенаправлены на обработчик следующим образом:

RewriteRule  ^(.+)\.*$ downloader.php?f=%{REQUEST_FILENAME} [L]

Назначение обработчика файла - псевдокодирование, за которым следует фактический код.

//Check if file exists and user is downloading from uploads directory; True.
//Check against a file type white list and set the mime type(); $ctype = mime type;
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");
header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filename));
readfile("$filename");

Со вчерашнего дня обработчик начал возвращать искаженные файлы, нечитаемые изображения и должен был быть обойден. Мне интересно, какие настройки могли пойти не так, чтобы вызвать это.

-EDIT-

Проблема найдена, но не решена. Включение пути к библиотеке php, которую я использовал для интеграции с Wordpress, приводило к повреждению файлов. Удаление этого блока кода решает проблему повреждения, но оставляет файлы доступными без требуемой аутентификации.

  @include_once($_SERVER['DOCUMENT_ROOT'].'/wp-blog-header.php');
  if(!is_user_logged_in()) 
  {
    auth_redirect(); //Kicks the user to a login page.
  }

  //resume download script

Ответы [ 2 ]

1 голос
/ 09 апреля 2010

Может быть, больше тестов покажет проблему ...

if ( !isset($filename) ) {
  die('parameter "filename" not set');
}
else if ( !file_exists($filename) ) {
  die('file does not exist');
}
else if ( !is_readable($filename) ) {
  die('file not readable');
}
else if ( false===($size=filesize($filename)) ) {
  die('stat failed');
}
else if ( headers_sent() || ob_get_length()>0) {
    die('something already sent output.');
}
else {
  $basename = basename($filename);

  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-Type: $ctype");
  header("Content-Disposition: attachment; filename=\"".$basename."\";" );
  header("Content-Transfer-Encoding: binary");
  header("Content-Length: ".$size);
  readfile($filename);
}
0 голосов
/ 09 апреля 2010

Как файлы повреждены? Усеченный? 0 байт? Совершенно другой контент? Случайные разделы заменены мусором?

Возможно ли, что ограничение памяти PHP сервера было снижено? readfile () будет буферизовать весь файл в памяти перед его выводом. Таким образом, файл 40 мегабайт потерпит неудачу, если предел памяти равен 39,9999, что-то в этом роде.

Для потоковой передачи файла пользователю лучше НЕ использовать собственные функции php «dump file to browser», поскольку все они ограничены объемом памяти. Лучше всего сделать цикл fopen / fwrite / fclose и выложить файл небольшими управляемыми кусками (4k, 16k и т. Д.).

...