PHP не признает свои собственные загруженные временные файлы

У меня тут настоящая головная боль.

Это моя конфигурация системы:

  • 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 и несколько 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: 

Вызов "сна" дает мне время проверить временный каталог на наличие файла, прежде чем он исчезнет.

Десятки поисков в Google привели меня к вещам, касающимся разрешений, или к решениям, которые связаны с неработающими формами загрузки, которые вообще не могут загружать что-либо. Файлы создаются на сервере, поэтому очевидно, что форма работает. Кроме того, я попытался предоставить IUSR, IIS_ISURS и DefaultAppPool полный доступ к временному каталогу и всему E: \ Inetpub_IIS, чтобы узнать, связано ли это с соответствующими разрешениями, но это ничего не изменило. Может ли кто-нибудь дать совет о том, что здесь происходит?

РЕДАКТИРОВАТЬ: Я понял это.

DaveRandom и я думали, что это проблема с правами доступа определенного типа, и это было правдой. Однако мы оба думали о разрешениях Windows, когда на самом деле проблема заключалась в разрешении / конфигурации PHP. Фраза Дейва «работать в обратном направлении» заставила меня задуматься о перемещении назад по дереву каталогов и проверке разрешений, что в конечном итоге привело к следующему решению.

Что я сделал:

Я написал очень короткий сценарий:

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

Это вернуло ЛОЖЬ. Очевидно, каталог не читался, как предположил Дэйв.

Я попробовал каталог 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 часов подряд без перерыва. Думаю, у меня чуть не случился инсульт.
9
задан Rich Adams 27 December 2011 в 23:09
поделиться