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

时间:2011-12-27 21:15:05

标签: 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 

如您所见,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();
}
?>

“logfile.txt”的内容:

$_FILES error: 
Permanent Filename: picture.jpg
Temp File Exists: 
Temp File Name: E:\Inetpub_IIS\tmp\php3F86.tmp
File Hash: 

存在“sleep”调用,让我有时间在文件临时目录消失之前检查该文件。

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

编辑:我明白了。

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

我做了什么:

我写了一个很短的剧本:

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

这返回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

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

open_basedir = E:\Inetpub_IIS\wwwroot

我将其更改为:

open_basedir = "E:\Inetpub_IIS\wwwroot;E:\Inetpub_IIS\tmp"

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

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

故事的道德:

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

1 个答案:

答案 0 :(得分:4)

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

我明白了。

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

我做了什么:

我写了一个很短的剧本:

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

这返回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

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

open_basedir = E:\Inetpub_IIS\wwwroot

我将其更改为:

open_basedir = "E:\Inetpub_IIS\wwwroot;E:\Inetpub_IIS\tmp"

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

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

故事的道德:

  • 检查open_basedir设置。
  • 启用,设置并记住检查您的php错误日志。
  • 连续7小时不要盯着同样的问题。我想我几乎中风了。