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

标签 php windows iis upload

我真的很头疼。

这是我的系统配置:

  • Windows 服务器 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 ”调用的存在让我有时间在文件消失之前检查临时目录。

数十次 Google 搜索让我找到了有关权限的问题,或者找到了涉及损坏的上传表单而根本无法上传任何内容的解决方案。这些文件是在服务器上创建的,所以很明显表格有效。此外,我已尝试授予 IUSR、IIS_ISURS 和 DefaultAppPool 对临时目录和所有 E:\Inetpub_IIS 的完全访问权限,以查看这是否与相关权限有关,但这并没有改变任何东西。谁能就这里发生的事情提供一些建议?

编辑:我想通了。

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

我做了什么:

我写了一个很短的脚本:

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

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

我尝试了 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"

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

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

故事的寓意:

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

最佳答案

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

我想通了。

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

我做了什么:

我写了一个很短的脚本:

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

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

我尝试了 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"

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

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

故事的寓意:

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

关于PHP 不会确认自己上传的临时文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8649365/

相关文章:

c++ - 以有限的生命周期运行 .exe?

c# - 如何在 WPF 中获取以编程方式创建的动态按钮的内容?

python - 15 秒空闲延迟加载 Windows 原生 Python 模块

asp.net - 无法启动 IIS Express Web 服务器

ASP.NET 和 AJAX 线程

c# - OAuth 2.0 不适用于本地 IIS

php - 从字符串中获取最后一个元素的更快方法

php - 如何使用mysql查询从每月数据中获取每日数据

php - 从多个表中选择多行

php - 验证 HTML 中的信息 - 代码定位