У меня возникла проблема с функцией PHP is_file()
.
Некоторые предварительные комментарии: я разрабатываю Ubuntu 12.04, 32-разрядный, используя PHP 5.5.10 и Apache 2.4.9.
В настоящее время я переписываю некоторый рабочий код, чтобы преобразовать его в библиотеку в Laravel (дополненную Facade и ServiceProvider). Я делаю это в основном для очистки кода, который я написал, когда был молодым и глупым (около 6 месяцев назад), и для проведения модульного тестирования. Библиотека, которую я пишу, предоставляет методы для заключения контракта (из которых два разных типа, с еще большим количеством) и поиск пути к PDF-документу (отсканированный бумажный контракт). Мои методы поиска пути работают нормально, и все тесты проходят.
В моем старом коде я использовал это:
/**
* Get a scanned contract and return it to the client
*
* @param string $type
* The contract type. Must be either static::CONTRACT1 or static::CONTRACT2.
*
* @param string $contract_id
* The contract ID
*
* @return Response
*/
public static function get($type, $contract_id)
{
// get the file name
//
$results = static::getFileName($type, $contract_id);
// did we find a file? if not, throw a ScannedContractNotFoundException
//
if(!$results)
throw new \MyApplication\Exceptions\ScannedContractNotFoundException("No file found for $type contract $contract_id");
// get the path and file name
//
$path = $results['path'];
$name = $results['name'];
// get the full path
//
$file = $path.$name;
// get the file size
//
$contents = file_get_contents($file);
$fsize = strlen($contents);
// push the file to the client
//
header("Content-type: application/pdf");
header("Content-Disposition: inline; filename=\"".$name."\"");
header("Content-length: $fsize");
header("Cache-control: private");
echo $contents;
exit;
}
И это сработало отлично.
Теперь я пытаюсь переписать его, чтобы избавиться от echo
и переместить код, который фактически выполняет работу по отправке файла на контроллер. Этот код будет выглядеть так:
$x = \MyApplication\Models\Contract1::find($id);
$file = \ScannedContracts::getFileName($x);
$path = $file["path"].$file["name"];
return \Response::download($path, $file["name"]);
Однако этот код бросает FileNotFoundException
. Код, в котором генерируется исключение, выглядит следующим образом:
public function __construct($path, $checkPath = true)
{
if ($checkPath && !is_file($path)) {
throw new FileNotFoundException($path);
}
...
Очевидно, что проблема связана с оператором if
и, в частности, с вызовом is_file()
.
Я написал немного script, чтобы проверить это с помощью пути, который, как известно, хорош, и is_file()
возвращает false.
Когда я копирую файл в свою "общедоступную" папку, он отлично работает.
Есть два возможных факторов: во-первых, файлы, с которыми я работаю, находятся на общем ресурсе CIFS/Samba. Я должен упомянуть, что рассматриваемые пути - это абсолютные пути к монтированной доле.
Ближайшая проблема с этим я нашел в SO PHP is_file возвращает false (неправильно) для общего ресурса Windows на Ubuntu, но это не имеет разрешения, Я также искал отчеты об ошибках PHP, но там ничего.
Во-вторых, некоторые из путей содержат пробелы. Я попытался убежать от них, как я могу себе представить, но это не помогает.
В отсутствие решения мне придется сделать это по-старому, но я действительно хотел сделать это, используя функции, которые предоставляет Laravel.
Нужно ли мне избегать пробелов в пути, переданном в is_file()
?
Кто-нибудь знает об исправлении или обходном пути, которые не требуют: a) требуют изменения кода в сторонней библиотеке или b) требуют оптовых изменений разрешений или другой конфигурации на сервере CIFS/Samba?
Спасибо заранее!
Я думаю, вам нужно санировать имена файлов при загрузке в каталог
function sanitize_file_name( $str ) {
return preg_replace("/[^a-z0-9\.]/", "", strtolower($str));
}
%20
-> кроме того, что он должен работать должным образом -> единственное, что если файл является чем-то иным, чем «обычный файл», он не будет работать - но я не вижу, что вы пытаетесь получить доступ к «Специальным файлам» в любом случае :-Pphp -r 'var_dump(is_file("/path/to/your/win/share"));'
? И, кстати, apache имеет доступ для чтения в этой папке? нет ограничений open_base_dir? нет safe_mode?