PHP не будет подтверждать свои собственные загруженные временные файлы - PullRequest
9 голосов
/ 28 декабря 2011

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

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

  • 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 часов подряд без перерыва.Я думаю, что у меня почти был инсульт.

1 Ответ

4 голосов
/ 28 декабря 2011

Как и было обещано, вот мой ответ. Это было скопировано / вставлено из редактирования OP.

Я понял это.

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 часов подряд. Я думаю, что у меня почти был инсульт.
...