2011-12-27 65 views
9

我在这里有一个真正的头部划痕。PHP将不会确认自己上传的临时文件

这是我的系统配置:

  • 的Windows Server 2008 R2
  • 安装为FastCGI的模块PHP 5.3.8
  • 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对象和一些div用于Flash对象构建表单,仅此而已。临时上传文件正在整个服务器上创建,因此我非常认真地怀疑我的表单是问题所在。

<?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: 

“休眠”呼叫存在,给我时间来检查临时目录中的文件消失之前。

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

编辑:我想通了。

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

我做了什么:

我写了一个很短的脚本:

<?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 

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

open_basedir = E:\Inetpub_IIS\wwwroot 

我把它改为:

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

重新启动应用程序开始发挥预期的服务器之后。

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

这个故事告诉我们(S):

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

[php man](http://www.php.net/manual/en/features.file-upload.php)查看错误代码部分以帮助您调试,同时查找[print_r](http: //)函数让你cxan做print_r($ _ FILES); – goat 2011-12-27 21:54:11

+0

返回UPLOAD_ERR_OK。下面是一些print_r输出:'Array([the_uploaded_file] => Array([name] => picture.jpg [type] => image/jpeg [tmp_name] => E:\ Inetpub_IIS \ tmp \ php34DD.tmp [error] = > 0 [size] => 391387))' – TPC 2011-12-27 22:05:16

+0

我知道你已经走过这条大道,但似乎这是与权限相关的 - 特别是(虽然这很奇怪)某些东西只能对目录进行只写访问 - 或者正在创建的文件 - 并且无法读取它/它们。尝试将完全控制权分配给“每个人”组,并查看是否可以解决问题,如果它从那里倒退。 – DaveRandom 2011-12-27 22:11:08

回答

4

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

我想通了。

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

我做了什么:

我写了一个很短的脚本:

<?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" 

重新启动应用程序开始发挥预期的服务器之后。

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

这个故事告诉我们(S):

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

我想指出的是,虽然这解决了眼前的问题,但并没有解释为什么PHP能够写入目录但无法读取它。我不知道这是否是偶然事件,合理的错误或配置问题。但无论如何,它现在起作用。 – TPC 2011-12-28 15:58:08

+0

记录良好的答案。 – xbonez 2011-12-29 06:06:34