2011-12-27 18 views
9

Tengo un verdadero head-scratcher aquí.PHP no confirma sus propios archivos temporales cargados

Esta es mi configuración del sistema:

  • Windows Server 2008 R2
  • PHP 5.3.8 instalado como un módulo FastCGI
  • IIS 7,5

Este es mi problema:

Tengo un formulario de carga de archivos simple. Como sabemos, cuando PHP acepta cargar un archivo, el archivo recibe un nombre temporal y se coloca en un directorio temporal antes de que se procese. En mi caso, PHP coloca el archivo en el directorio temporal (que resulta ser E: \ Inetpub_IIS \ tmp, al lado de E: \ Inetpub_IIS \ wwwroot) pero inmediatamente "olvida" que el archivo existe hasta que aparece el recolector de elementos no utilizados, que elimina el archivo temporal. Más específicamente, el archivo temporal se crea en el directorio temporal en el servidor, pero cuando llamo a sha1_file() en ese archivo, la función no devuelve nada. file_exists() también falla. Esto me hace pensar que PHP no puede encontrar el archivo. El registro de ProcMon a continuación muestra que PHP está buscando en el lugar correcto.

Aquí es mi registro 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 

Como se puede ver, ProcMon muestra claramente el archivo temporal que se está creando, por escrito y luego cerrada. Cerca del final puede ver las llamadas a "QueryDirectory", que coinciden con las llamadas de mi script, que intentan obtener el hash SHA1 del archivo, entre otras cosas.

Esta es mi guión:

El formulario de carga de archivos tiene un objeto Flash y algunos DIVs para el objeto Flash para crear la forma, nada más. El archivo de carga temporal se está creando en el servidor en su totalidad, así que dudo mucho que mi problema sea el problema.

<?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(); 
} 
?> 

El contenido de "logfile.txt":

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

existe la llamada "sueño" que me diera tiempo para comprobar el directorio temporal para el archivo antes de que desaparezca.

Decenas de búsquedas en Google me han llevado a cosas relacionadas con permisos, o a soluciones que implican formularios de carga rotos que no pueden cargar nada en absoluto. Los archivos se están creando en el servidor, así que obviamente el formulario funciona. Además, he intentado dar acceso completo a IUSR, IIS_ISURS y DefaultAppPool al directorio temporal y a todos los de E: \ Inetpub_IIS para ver si esto tenía algo que ver con los permisos asociados, pero eso no cambió nada. ¿Alguien puede ofrecer algún consejo sobre lo que está sucediendo aquí?

EDIT: Me di cuenta.

DaveRandom y yo pensamos que era un problema de permisos de algún tipo, que era cierto. Sin embargo, los dos estábamos pensando en los permisos de Windows, cuando el problema era realmente un problema de permisos/configuración de PHP. El fraseo de "trabajo hacia atrás" de Dave me hizo pensar en retroceder en el árbol de directorios y probar los permisos que finalmente produjeron la siguiente solución.

Lo que hice:

Escribí un guión muy corto:

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

Esto devuelve FALSE. Aparentemente, el directorio no era legible, como Dave sugirió.

Probé el directorio E: \ Inetpub_IIS \ wwwroot, que devolvió TRUE. Hmm. Luego me di cuenta de que había olvidado revisar el php_error.log todo el día. Aquí es lo que encontré:

[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 

Busqué en Google "restricción open_basedir en efecto" y tenía mi respuesta. En el archivo php.ini, open_basedir se estableció en:

open_basedir = E:\Inetpub_IIS\wwwroot 

me cambiaron a este:

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

Después de reiniciar el servidor de la aplicación comenzó a trabajar como estaba previsto.

Esperemos que sea suficiente documentación para alguien más que pueda estar teniendo el mismo problema.

Moral (s) de la historia:

  • comprobar los ajustes de open_basedir.
  • Habilite, configure y recuerde comprobar su registro de errores php.
  • No mire fijamente el mismo problema durante 7 horas seguidas sin interrupción. Creo que casi tuve un derrame cerebral.
+0

[php man] (http://www.php.net/manual/en/features.file-upload.php) vea la sección de códigos de error para ayudarlo a depurar, también busque [print_r] (http: //www.php.net/print_r)() función para que cxan do print_r ($ _ FILES); – goat

+0

Se devuelve UPLOAD_ERR_OK. Aquí hay algunos resultados de 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

+0

Sé que has estado en esta avenida, pero parece que se trata de permisos relacionados, específicamente (aunque sería extraño) que algo tiene acceso de solo escritura al directorio, o los archivos que se están creando y no pueden leerlos. Intente asignar control total al grupo 'Todos' y vea si eso soluciona el problema, si funciona hacia atrás desde allí. – DaveRandom

Respuesta

4

Según lo prometido, aquí está mi respuesta. Esto fue copiado/pegado de la edición OP.

Me di cuenta.

DaveRandom y yo pensamos que era un problema de permisos de algún tipo, que era cierto. Sin embargo, los dos estábamos pensando en los permisos de Windows, cuando el problema era realmente un problema de permisos/configuración de PHP. El fraseo de "trabajo hacia atrás" de Dave me hizo pensar en retroceder en el árbol de directorios y probar los permisos que finalmente produjeron la siguiente solución.

Lo que hice:

Escribí un guión muy corto:

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

Esto devuelve FALSE. Aparentemente, el directorio no era legible, como Dave sugirió.

Probé el directorio E: \ Inetpub_IIS \ wwwroot, que devolvió TRUE. Hmm. Luego me di cuenta de que había olvidado revisar el php_error.log todo el día. Esto es lo que encontré:

[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 

Busqué en Google "open_basedir restriction in effect" y tenía mi respuesta. En el php.ini, open_basedir se establece en:

open_basedir = E:\Inetpub_IIS\wwwroot 

me cambiaron a este:

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

Después de reiniciar el servidor de la aplicación comenzó a trabajar como estaba previsto.

Esperemos que sea suficiente documentación para alguien más que pueda estar teniendo el mismo problema.

Moral (s) de la historia:

  • comprobar los ajustes de open_basedir.
  • Habilite, configure y recuerde comprobar su registro de errores php.
  • No mire fijamente el mismo problema durante 7 horas seguidas. Creo que casi tuve un derrame cerebral.
+0

Me gustaría señalar que aunque esto resolvió el problema inmediato, no explicaba por qué PHP podía escribir en el directorio pero no podía leer de él. No sé si eso fue casualidad, un error legítimo o un problema de configuración. Pero como sea, funciona ahora. – TPC

+0

Respuesta bien documentada. – xbonez

Cuestiones relacionadas