¿Por qué $ _FILES estaría vacío al cargar archivos a PHP?

145

Tengo instalado WampServer 2 en mi computadora con Windows 7. Estoy usando Apache 2.2.11 y PHP 5.2.11. Cuando intento cargar cualquier archivo de un formulario, parece cargar, pero en PHP, la $_FILESmatriz está vacía. No hay archivo en la c:\wamp\tmpcarpeta. He configurado php.inipara permitir la carga de archivos y tal. La tmpcarpeta tiene privilegios de lectura / escritura para el usuario actual. Estoy perplejo.

HTML:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
    <form enctype="multipart/form-data" action="vanilla-upload.php" method="POST">
        Choose a file to upload: <input name="uploadedfile" type="file" /><br />
        <input type="submit" value="Upload File" />
    </form>
</body>
</html>

PHP:

<?php
echo 'file count=', count($_FILES),"\n";
var_dump($_FILES);
echo "\n";
?>
elmonty
fuente
2
¿Has revisado los registros de errores?
Byron Whitlock
Estoy seguro de que hay algo tonto que estás pasando por alto. Por ejemplo, ¿estás seguro de tener el código vanilla-upload.php?
Luca Matteis
Ja, estaba teniendo el mismo problema. Revisé los registros de errores y decía que se estaba cargando un archivo que excedía el tamaño máximo permitido.
BrightIntelDusk

Respuestas:

493

Aquí hay una lista de verificación para cargar archivos en PHP:

  1. Verifique php.ini para:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Es posible que necesite usar .htaccesso .user.inisi está en un alojamiento compartido y no tiene acceso php.ini.
    • Asegúrese de que está editando el archivo INI correcto: use la phpinfo()función para verificar que su configuración se esté aplicando realmente.
    • También asegúrese de no escribir mal los tamaños, no debería ser 100M así 100MB .
  2. Asegúrese de que su <form>etiqueta tenga el enctype="multipart/form-data"atributo. Ninguna otra etiqueta funcionará, tiene que ser su etiqueta FORM. Verifique que esté escrito correctamente . Verifique que los datos multiparte / formulario estén rodeados de COTIZACIONES DIRECTAS, no comillas inteligentes pegadas desde Word O desde un blog del sitio web (¡WordPress convierte comillas rectas en comillas angulares!). Si tiene varios formularios en la página, asegúrese de que ambos tengan este atributo. Escríbalos manualmente, o intente con comillas simples escritas manualmente.

  3. Asegúrese de no tener dos campos de archivo de entrada con el mismo nameatributo. Si necesita admitir múltiples, ponga corchetes al final del nombre:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Asegúrese de que sus directorios tmp y upload tengan los permisos correctos de lectura + escritura establecidos. La carpeta de carga temporal se especifica en la configuración de PHP como upload_tmp_dir.

  5. Asegúrese de que el destino de su archivo y los directorios tmp / upload no tengan espacios en ellos.

  6. Asegúrese de que todos <form>los elementos de su página tengan </form>etiquetas cercanas.

  7. Asegúrese de que su etiqueta FORM tenga method="POST". Las solicitudes GET no admiten cargas multiparte / datos de formulario.

  8. Asegúrese de que su etiqueta de entrada de archivo tenga un atributo NAME. ¡Un atributo de ID NO es suficiente! Los atributos de ID se usan en DOM, no para cargas POST.

  9. Asegúrese de no estar usando Javascript para deshabilitar su <input type="file">campo en el envío

  10. Asegúrate de no anidar formas como <form><form></form></form>

  11. Verifique su estructura HTML para etiquetas inválidas / superpuestas como <div><form></div></form>

  12. También asegúrese de que el archivo que está cargando no contenga caracteres no alfanuméricos.

  13. Una vez, pasé horas tratando de descubrir por qué esto me estaba sucediendo de repente. Resultó que había modificado algunas de las configuraciones de PHP .htaccess, y una de ellas (aún no estoy segura de cuál) estaba causando que la carga fallara y $_FILESquedara vacía.

  14. Podría intentar evitar los guiones bajos ( _) en el name=""atributo de la <input>etiqueta

  15. Intente cargar archivos muy pequeños para reducir si se trata de un problema de tamaño de archivo.

  16. Verifique su espacio disponible en disco. Aunque es muy raro, se menciona en este comentario de la página del Manual de PHP :

    Si la matriz $ _FILES de repente se queda misteriosamente vacía, a pesar de que su formulario parece correcto, debe verificar el espacio en disco disponible para su partición de carpeta temporal. En mi instalación, todas las cargas de archivos fallaron sin previo aviso. Después de mucho crujir de dientes, intenté liberar espacio adicional, después de lo cual la carga de archivos volvió a funcionar de repente.

  17. Asegúrese de no enviar el formulario a través de una solicitud POST de AJAX en lugar de una solicitud POST normal que hace que una página se vuelva a cargar. Revisé todos y cada uno de los puntos de la lista anterior, y finalmente descubrí que la razón por la cual mi variable $ _FILES estaba vacía era que estaba enviando el formulario usando una solicitud POST AJAX. Sé que también hay métodos para cargar archivos usando ajax, pero esta podría ser una razón válida por la que su matriz $ _FILES está vacía.

Fuente para algunos de estos puntos:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

shamittomar
fuente
12
Tal vez la respuesta "aceptada" resolvió la publicación original, pero esta respuesta es la que encontré más útil. En caso de duda, mire la fuente como la ve el navegador. Marcando cada elemento en esta lista y rastreando hacia atrás, encontré mi error en un lugar inesperado. Si estás luchando con un problema similar, créeme, probablemente no sea un error en Apache. ;)
quickthyme
3
También asegúrese de que su elemento de formulario que contiene la entrada del archivo NO sea hijo de otro elemento de formulario. eg<form><form><input type="file"></form></form>
sudee
3
¡Guauu! Gracias por esta lista. Mi problema era el # 2. Estaba llamando $('#my-form')[0].reset();en el controlador de envío.
Gavin
2
Gracias. en mi caso el número 7. enctype = "multipart / form-data" fue el culpable.
Thupten
3
Tío, eres un salvavidas. Pasé horas tratando de resolver esto (2) fue mi problema ... ¡Gracias!
Mike Q
74

En cuanto al HTML, parece que ha configurado esa parte correctamente. Ya tienes lo enctype="multipart/form-data"que es muy importante tener en el formulario.

En cuanto a su php.iniconfiguración, a veces en los sistemas php.iniexisten múltiples archivos. Asegúrese de estar editando el correcto. Sé que dijiste que configuraste tu php.iniarchivo para cargar archivos, pero ¿también configuraste upload_max_filesizey post_max_sizeser más grande que el archivo que estás intentando cargar? Entonces deberías tener:

file_uploads = On; sounds like you already did this
post_max_size = 8M; change this higher if needed
upload_max_filesize = 8M; change this higher if needed

¿Su directorio: "c:\wamp\tmp"tiene permisos de lectura y escritura? ¿Recordó reiniciar Apache después de realizar los php.inicambios?


Brian
fuente
44
+1: para reiniciar la sugerencia del servidor Apache. Muchos usuarios de Windows olvidan eso.
shamittomar
36

Es importante agregar enctype="multipart/form-data"a su formulario, ejemplo

<form action="upload.php" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>
meda
fuente
14

Gracias a todos por las variadas respuestas integrales. Esos son todos muy útiles. La respuesta resultó ser algo muy extraño. Resulta que PHP 5.2.11 no le gusta lo siguiente:

post_max_size = 2G

o

post_max_size = 2048M

Si lo cambio a 2047M, la carga funciona.

elmonty
fuente
17
Tenga en cuenta que un valor tan alto es una vulnerabilidad a los ataques fuera del espacio / ddos. Simplemente agregue esto para que las personas sepan que es demasiado, cuando intentan copiar y pegar su solución. De todos modos, 2 conciertos requerirían un tiempo de carga que es demasiado largo.
Manuel Arwed Schmidt
Ya no es demasiado grande. Tenemos clientes que cargan archivos en el rango 1-3G con bastante regularidad. Dado que están cargando archivos en sus propios servidores, y son servidores incluidos en la lista blanca de IP, el intercambio es bastante normal y es simplemente una forma de permitir que un cliente use su equipo de la manera que lo desee. Pagan las facturas, sin riesgos de seguridad, sin problemas.
TheSatinKnight
8

Tengo el mismo problema buscando 2 horas, es muy simple verificar primero la configuración de nuestro servidor.

Ejemplo:

echo $upload_max_size = ini_get('upload_max_filesize');  
echo $post_max_size=ini_get('post_max_size');   

cualquier tipo de tamaño de archivo es :20mb, pero nuestro upload_max_sizeestá arriba 20mbpero la matriz es null. La respuesta es nuestra post_max_sizedebería ser mayor que upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
shashik493
fuente
6

Aquí otra causa que encontré: Al usar JQuery Mobile y el atributo de formulario data-ajax está establecido en verdadero, la matriz de ARCHIVOS estará vacía. Establezca data-ajax en falso.

jaque mate711
fuente
5

Asegúrese de que su elemento de entrada tenga un atributo 'nombre'. <input type="file" name="uploadedfile" />

Si esto falta, los $ _FILES estarán vacíos.

Adrian Parr
fuente
4

Estaba luchando con el mismo problema y probando todo, sin obtener informes de errores y nada parecía estar mal. Tuve error_reporting (E_ALL) Pero de repente me di cuenta de que no había revisado el registro de apache y ¡voilà! ¡Hubo un error de sintaxis en el script ...! (falta un "}")

Entonces, aunque esto es algo evidente para verificar, puede olvidarse ... En mi caso (Linux) es en:

/var/log/apache2/error.log
Luis Rosety
fuente
3

Nadie mencionó esto, pero me ayudó y no muchos lugares en la red lo mencionan.

Asegúrese de que su php.ini establece la siguiente clave:

    upload_tmp_dir="/path/to/some/tmp/folder"

Tendrá que consultar con su webhost si quiere que use una ruta absoluta de archivo del servidor. Debería poder ver otros ejemplos de directorio en su archivo php.ini para determinar esto. Tan pronto como lo configuré, obtuve valores en mi objeto _FILES.

Finalmente, asegúrese de que su carpeta tmp y donde quiera que esté moviendo los archivos tengan los permisos correctos para que puedan leerse y escribirse en ellos.

AaronP
fuente
2

Si usted está tratando de subir una serie de archivos entonces es posible que tenga que aumentar max_file_uploadsen el php.inique está junto al conjunto predeterminado20

Nota : max_file_uploadsNO se puede cambiar fuera de php.ini. Ver PHP "Bug" # 50684

Tahir Yasin
fuente
2

Otro posible culpable es el redireccionamiento de apache. En mi caso, configuré httpd.conf de apache para redirigir ciertas páginas de nuestro sitio a versiones http y otras páginas a versiones https de la página, si aún no lo estaban. La página en la que tenía un formulario con una entrada de archivo era una de las páginas configuradas para forzar ssl, pero la página designada como la acción del formulario estaba configurada para ser http. Por lo tanto, la página enviaría la carga a la versión SSL de la página de acción, pero Apache la estaba redirigiendo a la versión http de la página y se perdieron los datos de publicación, incluido el archivo cargado.

usuario2723315
fuente
1

Si su script principal es http://Some_long_URL/index.phpcuidadoso, especifique la URL completa (con explícito index.phpy no solo http://Some_long_URL) en el actioncampo. Sorprendentemente, si no, se ejecuta el script correcto, ¡pero con $ _FILES en vacío!

Gibbie
fuente
1

Me encontré con el mismo problema y descubrí que era mi IDE parte del problema. Estaba iniciando el depurador directamente desde el IDE (PHPStorm) en lugar de simplemente usar el navegador directamente. La URL generada por IDE era así:

"...localhost:63342/CB_Upload/index.php?_ijt=j2hcbacqepj87bvg66ncuohvne"

y solo usando:

"...localhost/CB_Upload/index.php"

funcionó bien. Mi configuración es PC / Windows 10 / WAMPSERVER 3.0.6 64bit

Marc M.
fuente
Lo mismo aquí, ¡estuve corriendo en círculos durante una hora hasta ahora! gracias
EKanadily
1

No confíe en la ubicación de la carpeta temporal proporcionada por sys_get_temp_dir si está en un entorno de alojamiento compartido.

Aquí hay una cosa más para verificar que aún no se ha mencionado ...

Supuse, naturalmente, que la carpeta donde mi script PHP almacenaba las cargas de archivos temporales era /tmp. Esta creencia fue reforzada por el hecho de que echo sys_get_temp_dir() . PHP_EOL;regresa /tmp. También,echo ini_get('upload_tmp_dir'); no devuelve nada.

Para verificar que el archivo cargado aparece de hecho brevemente en mi /tmpcarpeta, agregué una sleep(30);declaración a mi script (como se sugiere aquí ) y navegué a mi/tmp carpeta en el Administrador de archivos de cPanel para ubicar el archivo. Sin embargo, no importa qué, el archivo cargado no se encontraba en ninguna parte.

Pasé horas tratando de determinar la razón de esto, e implementé todas las sugerencias que se ofrecen aquí.

Finalmente, después de buscar la consulta en los archivos de mi sitio web tmp, descubrí que mi sitio contenía otras carpetas nombradas tmpen diferentes directorios. Me di cuenta de que mi script PHP en realidad estaba escribiendo los archivos cargados .cagefs/tmp. (El "Mostrar archivos ocultos" configuración debe estar habilitada en cPanel para ver esta carpeta).

Entonces, ¿por qué la sys_get_temp_dirfunción devuelve información inexacta?

Aquí hay una explicación de la página web PHP.net para sys_get_temp_dir(es decir, el comentario principal):

Si se ejecuta en un sistema Linux donde systemd tiene PrivateTmp = true (que es el valor predeterminado en CentOS 7 y quizás otras distribuciones más nuevas), esta función simplemente devolverá "/ tmp", no la ruta verdadera, mucho más larga y algo dinámica.

Esta publicación SO también profundiza en el problema:

Grillos
fuente
0

Tengo el mismo problema y ninguno de tema fue mi error. Revise su archivo .htaccess, si tiene uno, si "MultiViews" están habilitados. Tuve que desactivarlos.

Murolack
fuente
0

Tuve un problema similar y el problema tenía un valor incorrecto en htaccess como se mencionó en shamittomar.

Cambiar php_value post_max_size 10MBaphp_value post_max_size 10M

Johnny Vietnam
fuente
0

Estaba vacío $_FILESporque después de <form enctype="multipart/form-data" method="post">colocar

</div>
<div style="clear:both"></div>

El código inicial fue como

<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>

Decidí modificar y

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
<form enctype="multipart/form-data" method="post">
</div>
<div style="clear:both"></div>
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>

Entonces, la conclusión es que after <form enctype="multipart/form-data" method="post">debe ser <input name, type, idy no debe ser <div>o algunas otras etiquetas

En mi situación, el código correcto era

<div>
<span class="span_left">Photos (gif/jpg/jpeg/png) </span>
</div>
<div style="clear:both"></div>
<form enctype="multipart/form-data" method="post">
<input name="files[]" type="file" id="upload_file" />
<input type="button" id="upload" value="Upload photo" />
</form>
<div style="clear:both"></div>
Andris
fuente
0

Yo también tuve problemas con $ _FILES vacío. La lista de verificación anterior no menciona MultiViews en .htaccess, httpd.conf o httpd-vhost.conf.

Si tiene MultiViews establecido en la directiva de opciones para su directorio que contiene el sitio web, $ _FILES estará vacío, aunque el encabezado Content-Length si muestra que el archivo lo he subido.

gerteb
fuente
0

Si está utilizando JQuery Mobile

El uso de un formulario multiparte con una entrada de archivo no es compatible con Ajax. En este caso, debe decorar el formulario principal con data-ajax = "false" para asegurarse de que el formulario se envíe correctamente al servidor.

<form action="upload.php" method="post" enctype="multipart/form-data"  data-ajax="false">
    Select image to upload:
    <input type="file" name="fileToUpload" id="fileToUpload">
    <input type="submit" value="Upload Image" name="submit">
</form>
Rajan
fuente
0

Separe su formulario de la página que está utilizando en una página php simple que solo tiene el formulario y el código php, y pruébelo así.

Cualquier secuencia de comandos de arranque o Java podría limpiar el _FILES []. Ese fue mi caso

usuario2195463
fuente