PHP不会确认自己上传的临时文件

TPC*_*TPC 9 php windows iis upload

我在这里有一个真正的头脑.

这是我的系统配置:

  • Windows Server 2008 R2
  • PHP 5.3.8作为FastCGI模块安装
  • IIS 7.5

这是我的问题:

我有一个简单的文件上传表单.众所周知,当PHP接受文件上载时,该文件会被赋予一个临时名称,并在处理之前放在临时目录中.在我的例子中,PHP将文件放在临时目录(恰好是E:\ Inetpub_IIS\tmp,E:\ Inetpub_IIS\wwwroot旁边),然后立即"忘记"文件存在,直到垃圾收集器出现,删除临时文件.更具体地说,临时文件是在服务器上的临时目录中创建的,但是当我在该文件上调用sha1_file()时,该函数不返回任何内容.file_exists()也失败了.这让我觉得PHP无法找到该文件.下面的ProcMon日志显示PHP正在寻找合适的位置.

这是我的ProcMon日志:

2:43:14.9175650 PM  php-cgi.exe 5020    CreateFile  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Desired Access: Generic Read, Disposition: Create, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: None, AllocationSize: 0, Impersonating: NT AUTHORITY\IUSR, OpenResult: Created
2:43:14.9182596 PM  php-cgi.exe 5020    CloseFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS 
2:43:14.9184424 PM  php-cgi.exe 5020    QueryOpen   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS CreationTime: 12/27/2011 2:43:14 PM, LastAccessTime: 12/27/2011 2:43:14 PM, LastWriteTime: 12/27/2011 2:43:14 PM, ChangeTime: 12/27/2011 2:43:14 PM, AllocationSize: 0, EndOfFile: 0, FileAttributes: A
2:43:14.9185907 PM  php-cgi.exe 5020    CreateFile  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Desired Access: Write Attributes, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: NT AUTHORITY\IUSR, OpenResult: Opened
2:43:14.9187896 PM  php-cgi.exe 5020    SetBasicInformationFile E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS CreationTime: 0, LastAccessTime: 0, LastWriteTime: 0, ChangeTime: 0, FileAttributes: AN
2:43:14.9188368 PM  php-cgi.exe 5020    CloseFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS 
2:43:14.9190234 PM  php-cgi.exe 5020    CreateFile  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Desired Access: Generic Read/Write, Disposition: OverwriteIf, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: 0, Impersonating: NT AUTHORITY\IUSR, OpenResult: Overwritten
2:43:14.9193771 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 0, Length: 5,119, Priority: Normal
2:43:14.9489663 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 5,119, Length: 5,119, Priority: Normal
2:43:14.9730524 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 10,238, Length: 5,119
2:43:15.0054693 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 15,357, Length: 5,119, Priority: Normal
2:43:15.0309328 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 20,476, Length: 5,119
2:43:15.0633978 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 25,595, Length: 5,119
2:43:15.0879028 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 30,714, Length: 5,119, Priority: Normal
...
2:43:17.1849721 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 383,925, Length: 5,119
2:43:17.1851664 PM  php-cgi.exe 5020    WriteFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Offset: 389,044, Length: 2,343
2:43:17.1852283 PM  php-cgi.exe 5020    CloseFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS 
2:43:17.5070914 PM  php-cgi.exe 5020    QueryDirectory  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Filter: php3F86.tmp, 1: php3F86.tmp
2:43:17.5083973 PM  php-cgi.exe 5020    QueryDirectory  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Filter: php3F86.tmp, 1: php3F86.tmp
2:43:17.5112593 PM  php-cgi.exe 5020    QueryDirectory  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Filter: php3F86.tmp, 1: php3F86.tmp
2:43:17.5120519 PM  php-cgi.exe 5020    QueryDirectory  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Filter: php3F86.tmp, 1: php3F86.tmp
2:43:27.5512956 PM  php-cgi.exe 5020    CreateFile  E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
2:43:27.5515084 PM  php-cgi.exe 5020    QueryAttributeTagFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Attributes: A, ReparseTag: 0x0
2:43:27.5515406 PM  php-cgi.exe 5020    SetDispositionInformationFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS Delete: True
2:43:27.5515879 PM  php-cgi.exe 5020    CloseFile   E:\Inetpub_IIS\tmp\php3F86.tmp  SUCCESS 
Run Code Online (Sandbox Code Playgroud)

如您所见,ProcMon清楚地显示正在创建,写入然后关闭的临时文件.接近结尾,你可以看到"QueryDirectory"调用,它与我的脚本调用一致,它试图获取文件的SHA1哈希值.

这是我的脚本:

文件上载表单有一个Flash对象和Flash对象的一些DIV来构建表单,仅此而已.临时上传文件正在整个服务器上创建,所以我非常怀疑我的表单是问题所在.

<?php
// *******************************************************************
// exhibit-upload.php
// 
// *******************************************************************

// Reset same session ID because Adobe Flash is a flaming pile
session_id($_POST['sessionid']);

ob_start("ob_gzhandler");
require_once('inc-common.php');

$logFile = "logfile.txt";
$logHandle = fopen($logFile, 'w');

fwrite($logHandle, '$_FILES error: ' . $_FILES['error'] . "\n");

if(!empty($_FILES))
{
    // Get temp file
    $sFileTemp = $_FILES['Filedata']['tmp_name'];
    $sFileName = $objMySQL->sanitize($_FILES['Filedata']['name']);

    fwrite($logHandle, "Permanent Filename: " . $sFileName . "\n");

    $aFileBits = explode('.', $_FILES['Filedata']['name']);
    $sFileExt = $aFileBits[count($aFileBits) - 1];

    // Get SHA1 hash
    $sFileHash = sha1_file($sFileTemp);

    fwrite($logHandle, "Temp File Exists: " . file_exists($sFileTemp) . "\n");
    fwrite($logHandle, "Temp File Name: " . $sFileTemp . "\n");
    fwrite($logHandle, "File Hash: " . $sFileHash . "\n");
    sleep(10);
    exit();
}
?>
Run Code Online (Sandbox Code Playgroud)

"logfile.txt"的内容:

$_FILES error: 
Permanent Filename: picture.jpg
Temp File Exists: 
Temp File Name: E:\Inetpub_IIS\tmp\php3F86.tmp
File Hash: 
Run Code Online (Sandbox Code Playgroud)

存在"睡眠"调用,让我有时间在文件消失之前检查文件的临时目录.

数十次谷歌搜索引发了我关于权限的问题,或者涉及破坏的上传表单的解决方案,这些表单根本无法上传任何内容.正在服务器上创建文件,因此表单显然有效.此外,我尝试给IUSR,IIS_ISURS和DefaultAppPool完全访问临时目录和所有E:\ Inetpub_IIS以查看这是否与相关权限有关,但没有改变任何内容.有人可以就这里发生的事情提供一些建议吗?

编辑:我明白了.

DaveRandom和我都认为这是某种类型的权限问题,这是真的.但是,当问题实际上是PHP权限/配置问题时,我们都在考虑Windows权限.Dave的"向后工作"措辞让我想到了向后移动目录树并测试权限,最终产生了以下解决方案.

我做了什么:

我写了一个很短的脚本:

<?php
    //phpinfo();
    echo "Readable: " . is_readable('E:\Inetpub_IIS\tmp');
?>
Run Code Online (Sandbox Code Playgroud)

这返回FALSE.显然,目录是不可读的,正如戴夫建议的那样.

我尝试了E:\ Inetpub_IIS\wwwroot目录,该目录返回TRUE.嗯.然后我意识到我整天都没有检查php_error.log.这是我发现的:

[27-Dec-2011 16:51:43] PHP Warning:  is_readable(): open_basedir restriction in effect. File(E:\Inetpub_IIS\tmp) is not within the allowed path(s): (E:\Inetpub_IIS\wwwroot) in E:\Inetpub_IIS\wwwroot\ipl\info.php on line 3
Run Code Online (Sandbox Code Playgroud)

我用谷歌搜索"open_basedir限制有效"并得到我的答案.在php.ini文件中,open_basedir设置为:

open_basedir = E:\Inetpub_IIS\wwwroot
Run Code Online (Sandbox Code Playgroud)

我改为:

open_basedir = "E:\Inetpub_IIS\wwwroot;E:\Inetpub_IIS\tmp"
Run Code Online (Sandbox Code Playgroud)

重新启动服务器后,应用程序开始按预期工作.

希望这对于可能遇到同样问题的其他人来说是足够的文档.

故事的道德:

  • 检查open_basedir设置.
  • 启用,设置并记住检查您的php错误日志.
  • 不要在没有休息的情况下连续7个小时盯着同样的问题.我想我几乎中风了.

TPC*_*TPC 4

正如所承诺的,这是我的答案。这是从 OP 编辑​​中复制/粘贴的。

我想到了。

DaveRandom 和我都认为这是某种类型的权限问题,这是事实。然而,当问题实际上是 PHP 权限/配置问题时,我们都在考虑 Windows 权限。戴夫的“向后工作”措辞让我考虑向后移动目录树并测试权限,最终产生了以下解决方案。

我做了什么:

我写了一个很短的脚本:

<?php
    //phpinfo();
    echo "Readable: " . is_readable('E:\Inetpub_IIS\tmp');
?>
Run Code Online (Sandbox Code Playgroud)

这返回 FALSE。显然,正如戴夫所建议的那样,该目录不可读。

我尝试了E:\Inetpub_IIS\wwwroot目录,结果返回TRUE。唔。然后我意识到我一整天都忽略了检查 php_error.log。这是我发现的:

[27-Dec-2011 16:51:43] PHP Warning:  is_readable(): open_basedir restriction in effect. File(E:\Inetpub_IIS\tmp) is not within the allowed path(s): (E:\Inetpub_IIS\wwwroot) in E:\Inetpub_IIS\wwwroot\ipl\info.php on line 3
Run Code Online (Sandbox Code Playgroud)

我在谷歌上搜索了“open_basedir 限制有效”并得到了答案。在 php.ini 文件中,open_basedir 设置为:

open_basedir = E:\Inetpub_IIS\wwwroot
Run Code Online (Sandbox Code Playgroud)

我将其更改为:

open_basedir = "E:\Inetpub_IIS\wwwroot;E:\Inetpub_IIS\tmp"
Run Code Online (Sandbox Code Playgroud)

重新启动服务器后,应用程序开始按预期工作。

希望这对于其他可能遇到同样问题的人来说是足够的文档。

这个故事的寓意:

  • 检查您的 open_basedir 设置。
  • 启用、设置并记得检查你的 php 错误日志。
  • 不要连续7个小时盯着同一个问题。我想我差点中风了。