【问题标题】:is_file always returns falseis_file 总是返回 false
【发布时间】:2014-04-11 18:08:00
【问题描述】:

问题

我遇到了 PHP 函数 is_file() 的问题。

一些准备工作:我正在使用 PHP 5.5.10 和 Apache 2.4.9 在 Ubuntu 12.04 32 位上进行开发。

我目前正在重写一些工作代码以将其转换为 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() 的调用。

我已经编写了一个小脚本来测试这个路径,该路径已知是好的,is_file() 返回 false。

当我将文件复制到我的“公共”文件夹时,它工作正常。

the documentation for the is_file() function 中有一条注释指出父文件夹的权限必须是+x。我检查了权限,该文件夹是全球可执行的,父级、祖父级和曾祖父级等也是如此。

有两个可能的混淆因素:首先,我正在使用的文件位于 CIFS/Samba 共享上。我应该提到,有问题的路径是已安装共享的绝对路径。

我在 SO 上找到的与此最接近的问题是 PHP is_file returns false (incorrectly) for Windows share on Ubuntu,但没有解决方案。我也搜索过 PHP 错误报告,但什么都没有。

其次,一些路径包含空格。我已经尝试了各种我能想到的方式来逃避它们,但它没有帮助。

在没有解决方案的情况下,我将不得不用老式的方式来做,但我真的很想用 Laravel 提供的功能来做。

问题

  1. 我是否需要在传递给is_file() 的路径中转义空格?

  2. 是否有人知道以下修复或解决方法:a) 需要更改 3rd 方库中的代码,或 b) 需要对 CIFS/Samba 服务器上的权限或其他配置进行大规模更改?

提前致谢!

【问题讨论】:

  • 1. -> 是的 - 你不能使用空格,用 %20 替换空格 -> 除了它应该按预期工作 -> 唯一的问题是,如果文件不是“常规文件”,它将无法工作 - 但是无论如何,我看不到您尝试以这种方式访问​​“特殊文件”:-P
  • 您是否尝试在 cli 中执行 php -r 'var_dump(is_file("/path/to/your/win/share"));' ?顺便说一句,apache 是否对该文件夹具有读取权限?没有 open_base_dir 限制?没有安全模式?
  • @naab 它是一个 Web 应用程序,为了回答您关于环境的所有其他问题,我能够使用旧代码从共享中下载完全相同的文件。我确实测试了is_file("/path/to/my/win/share/file.pdf"),它返回错误。
  • @GrahamRitchie “是的 - 你不能使用空格” - php -r 'var_dump(is_file("/tmp/toto a/a"));' prints : bool(true)(并且文件存在)
  • @GrahamRitchie 我尝试用 %20%020 替换路径中的空格 - 都没有用。

标签: php symfony laravel


【解决方案1】:

我认为您需要在上传到目录时清理文件名

function sanitize_file_name( $str ) {
    return preg_replace("/[^a-z0-9\.]/", "", strtolower($str));
}

【讨论】:

    猜你喜欢
    • 2012-08-23
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多