Pourquoi $ _FILES serait-il vide lors du téléchargement de fichiers vers PHP?

145

J'ai WampServer 2 installé sur mon ordinateur Windows 7. J'utilise Apache 2.2.11 et PHP 5.2.11. Lorsque j'essaye de télécharger un fichier à partir d'un formulaire, il semble télécharger, mais en PHP, le $_FILEStableau est vide. Il n'y a aucun fichier dans le c:\wamp\tmpdossier. J'ai configuré php.inipour autoriser les téléchargements de fichiers et autres. Le tmpdossier dispose de privilèges de lecture / écriture pour l'utilisateur actuel. Je suis perplexe.

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
la source
2
Avez-vous vérifié les journaux d'erreurs?
Byron Whitlock
Je suis sûr qu'il y a quelque chose de stupide que vous oubliez. Par exemple, êtes-vous sûr d'avoir le code vanilla-upload.php?
Luca Matteis
Ha j'avais le même problème. J'ai vérifié les journaux d'erreurs et il a dit qu'un fichier était en cours de téléchargement qui dépassait la taille maximale autorisée.
BrightIntelDusk

Réponses:

493

Voici une liste de contrôle pour le téléchargement de fichiers en PHP:

  1. Vérifiez php.ini pour:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Vous devrez peut-être utiliser .htaccessou .user.inisi vous êtes sur un hébergement partagé et n'avez pas accès à php.ini.
    • Assurez-vous que vous modifiez le bon fichier ini - utilisez la phpinfo()fonction pour vérifier que vos paramètres sont effectivement appliqués.
    • Assurez-vous également de ne pas mal orthographier les tailles - cela ne devrait 100M pas être le cas 100MB.
  2. Assurez-vous que votre <form>balise possède l' enctype="multipart/form-data"attribut. Aucune autre balise ne fonctionnera, il doit s'agir de votre balise FORM. Vérifiez qu'il est correctement orthographié . Vérifiez que les données multipart / form sont entourées de guillemets droits, et non de guillemets intelligents collés à partir de Word OU d'un blog de site Web (WordPress convertit les guillemets droits en guillemets angulaires!). Si vous avez plusieurs formulaires sur la page, assurez-vous qu'ils ont tous les deux cet attribut. Saisissez-les manuellement ou essayez les guillemets simples saisis manuellement.

  3. Assurez-vous que vous n'avez pas deux champs de fichier d'entrée avec le même nameattribut. Si vous avez besoin de prendre en charge plusieurs, mettez des crochets à la fin du nom:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Assurez-vous que vos répertoires tmp et upload disposent des autorisations de lecture et d'écriture correctes. Le dossier de téléchargement temporaire est spécifié dans les paramètres PHP comme upload_tmp_dir.

  5. Assurez-vous que vos répertoires de destination de fichier et tmp / upload ne contiennent pas d'espaces.

  6. Assurez-vous que tous <form>les éléments de votre page comportent </form>des balises proches.

  7. Assurez-vous que votre balise FORM a method="POST". Les requêtes GET ne prennent pas en charge les téléchargements de données en plusieurs parties / formulaire.

  8. Assurez-vous que votre balise d'entrée de fichier a un attribut NAME. Un attribut ID n'est PAS suffisant! Les attributs ID sont à utiliser dans le DOM, pas pour les charges utiles POST.

  9. Assurez-vous que vous n'utilisez pas Javascript pour désactiver votre <input type="file">champ lors de la soumission

  10. Assurez-vous de ne pas imbriquer des formulaires comme <form><form></form></form>

  11. Vérifiez votre structure HTML pour les balises non valides / qui se chevauchent comme <div><form></div></form>

  12. Assurez-vous également que le fichier que vous téléchargez ne contient aucun caractère non alphanumérique.

  13. Une fois, je viens de passer des heures à essayer de comprendre pourquoi cela m'arrivait tout d'un coup. Il s'est avéré que j'avais modifié certains des paramètres PHP dans .htaccess, et l'un d'entre eux ( je ne sais pas encore lequel) provoquait l'échec du téléchargement et $_FILESle vidage.

  14. Vous pouvez potentiellement essayer d'éviter les traits de soulignement ( _) dans l' name=""attribut de la <input>balise

  15. Essayez de télécharger de très petits fichiers pour déterminer s'il s'agit d'un problème de taille de fichier.

  16. Vérifiez votre espace disque disponible. Bien que très rare, il est mentionné dans ce commentaire de page de manuel PHP :

    Si le tableau $ _FILES devient soudainement mystérieusement vide, même si votre formulaire semble correct, vous devriez vérifier l'espace disque disponible pour votre partition de dossiers temporaires. Dans mon installation, tous les téléchargements de fichiers ont échoué sans avertissement. Après de nombreux grincements de dents, j'ai essayé de libérer de l'espace supplémentaire, après quoi les téléchargements de fichiers ont soudainement fonctionné à nouveau.

  17. Assurez-vous que vous ne soumettez pas le formulaire via une requête AJAX POST au lieu d'une requête POST normale qui provoque le rechargement d'une page. J'ai parcouru chaque point de la liste ci-dessus et j'ai finalement découvert que la raison pour laquelle ma variable $ _FILES était vide était que je soumettais le formulaire en utilisant une requête AJAX POST. Je sais qu'il existe également des méthodes pour télécharger des fichiers en utilisant ajax, mais cela pourrait être une raison valable pour laquelle votre tableau $ _FILES est vide.

Source pour certains de ces points:
http://getluky.net/2004/10/04/apachephp-_files-array-mysterously-empty/

shamittomar
la source
12
Peut-être que la réponse «acceptée» a résolu le message d'origine, mais cette réponse est celle que j'ai trouvée la plus utile. En cas de doute, regardez la source vue par le navigateur. En cochant chaque élément de cette liste et en remontant en arrière, j'ai trouvé mon erreur dans un endroit des plus inattendu. Si vous êtes aux prises avec un problème similaire, croyez-moi, ce n'est probablement pas un bogue dans Apache. ;)
quickthyme
3
Assurez-vous également que votre élément de formulaire contenant l'entrée de fichier n'est PAS un enfant d'un autre élément de formulaire. eg<form><form><input type="file"></form></form>
sudee
3
Hou la la! Merci pour cette liste. mon problème était le n ° 2. J'appelais $('#my-form')[0].reset();le gestionnaire de soumission.
Gavin
2
Merci. dans mon cas numéro 7. enctype = "multipart / form-data" était le coupable.
Jeudi
3
DUDE, vous êtes une bouée de sauvetage. Je passe des heures à essayer de comprendre que (2) était mon problème ... Merci!
Mike Q
74

En ce qui concerne le HTML, vous semblez avoir configuré cette partie correctement. Vous avez déjà le enctype="multipart/form-data"qui est très important d'avoir sur le formulaire.

En ce qui concerne votre php.iniconfiguration, il php.iniexiste parfois sur les systèmes plusieurs fichiers. Assurez-vous que vous modifiez le bon. Je sais que vous avez dit que vous avez configuré votre php.inifichier pour avoir des téléchargements de fichiers, mais avez-vous également défini votre upload_max_filesizeet post_max_sizepour qu'il soit plus grand que le fichier que vous essayez de télécharger? Vous devriez donc avoir:

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

Votre répertoire: "c:\wamp\tmp"dispose-t-il des autorisations de lecture et d'écriture? Avez-vous pensé à redémarrer Apache après avoir effectué les php.inimodifications?


Brian
la source
4
+1: Pour redémarrer l'astuce du serveur Apache. De nombreux utilisateurs de Windows oublient cela.
shamittomar
36

Il est important d'ajouter enctype="multipart/form-data"à votre formulaire, exemple

<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
la source
14

Merci à tous pour les réponses variées et complètes. Tout cela est très utile. La réponse s'est avérée être quelque chose de très étrange. Il s'avère que PHP 5.2.11 n'aime pas ce qui suit:

post_max_size = 2G

ou

post_max_size = 2048M

Si je le change en 2047M, le téléchargement fonctionne.

Elmonty
la source
17
Notez qu'une valeur aussi élevée est une vulnérabilité aux attaques hors espace / ddos. Il suffit d'ajouter ceci pour que les gens sachent que c'est trop, lorsqu'ils essaient de copier et coller votre solution. Quoi qu'il en soit, 2 concerts nécessiteraient un temps de téléchargement beaucoup trop long.
Manuel Arwed Schmidt
Pas trop grand plus. Nous avons des clients qui téléchargent assez régulièrement des fichiers de la gamme 1-3G. Puisqu'ils téléchargent des fichiers sur leurs propres serveurs, et qu'ils sont des serveurs IP sur liste blanche, l'échange est tout à fait normal et simplement un moyen de permettre à un client d'utiliser son équipement comme il le souhaite. Ils paient les factures, aucun risque pour la sécurité, aucun problème.
TheSatinKnight
8

J'ai un même problème en regardant 2 heures, c'est très simple de vérifier d'abord la configuration de notre serveur.

Exemple:

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

tout type de taille de fichier l'est :20mb, mais notre upload_max_sizeest au-dessus 20mbmais le tableau l'est null. La réponse est que notre post_max_sizedevrait être supérieur à upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
shashik493
la source
6

Voici une autre cause que j'ai trouvée: lorsque vous utilisez JQuery Mobile et que l'attribut de formulaire data-ajax est défini sur true, le tableau FILES sera vide. Définissez donc data-ajax sur false.

échec et mat711
la source
5

Assurez-vous que votre élément d'entrée a un attribut «nom». <input type="file" name="uploadedfile" />

Si cela manque, $ _FILES sera vide.

Adrian Parr
la source
4

Je luttais avec le même problème et je testais tout, je n'obtenais pas de rapport d'erreur et rien ne semblait aller de travers. J'ai eu error_reporting (E_ALL) Mais du coup j'ai réalisé que je n'avais pas vérifié le journal Apache et voilà! Il y a eu une erreur de syntaxe sur le script ...! (un "}" manquant)

Donc, même si c'est quelque chose d'évident à vérifier, on peut l'oublier ... Dans mon cas (linux) c'est à:

/var/log/apache2/error.log
Luis Rosety
la source
3

Personne n'a mentionné cela, mais cela m'a aidé et peu d'endroits sur le net le mentionnent.

Assurez-vous que votre php.ini définit la clé suivante:

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

Vous devrez vérifier auprès de votre hébergeur s'il souhaite que vous utilisiez un chemin de fichier serveur absolu. Vous devriez pouvoir voir d'autres exemples de répertoires dans votre fichier php.ini pour le déterminer. Dès que je l'ai défini, j'ai des valeurs dans mon objet _FILES.

Enfin, assurez-vous que votre dossier tmp et l'endroit où vous déplacez des fichiers disposent des autorisations appropriées afin qu'ils puissent être lus et écrits.

AaronP
la source
2

Si vous essayez de télécharger un tableau de fichiers, vous devrez peut - être augmenter max_file_uploadsdans ce php.iniqui est par défaut ensemble20

Remarque : max_file_uploadsne peut PAS être modifié en dehors de php.ini. Voir le "bogue" PHP # 50684

Tahir Yasin
la source
2

Les redirections Apache sont un autre coupable possible. Dans mon cas, j'ai configuré httpd.conf d'apache pour rediriger certaines pages de notre site vers des versions http, et d'autres pages vers des versions https de la page, si elles ne l'étaient pas déjà. La page sur laquelle j'avais un formulaire avec une entrée de fichier était l'une des pages configurées pour forcer ssl, mais la page désignée comme l'action du formulaire était configurée pour être http. Ainsi, la page soumettrait le téléchargement à la version ssl de la page d'action, mais Apache le redirigeait vers la version http de la page et les données de publication, y compris le fichier téléchargé, étaient perdues.

utilisateur2723315
la source
2

Vérifiez votre php.ini pour enable_post_data_reading = On , car:

La désactivation de cette option fait que $ _POST et $ _FILES ne sont pas remplis . Le seul moyen de lire les données postales sera alors via le wrapper de flux d'entrée php: //. (...)

Dans http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading

jmng
la source
1

Si votre script principal est http://Some_long_URL/index.phpattentif à spécifier l'URL complète (avec explicite index.phpet pas seulement http://Some_long_URL) dans le actionchamp. Étonnamment, sinon, le bon script est exécuté, mais avec en vide $ _FILES!

Gibbie
la source
1

J'ai rencontré le même problème et j'ai découvert que mon IDE faisait partie du problème. Je lançais le débogueur directement depuis l'IDE (PHPStorm) au lieu d'utiliser simplement le navigateur directement. L'URL générée par l'EDI était comme ceci:

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

et en utilisant simplement:

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

a très bien fonctionné. Ma configuration est PC / Windows 10 / WAMPSERVER 3.0.6 64 bits

Marc M.
la source
même chose ici, j'ai tourné en rond pendant une heure jusqu'à présent! merci
EKanadily
1

Ne faites pas confiance à l'emplacement du dossier temporaire fourni par sys_get_temp_dirsi vous êtes dans un environnement d'hébergement partagé.

Voici encore une chose à vérifier qui n'a pas encore été mentionnée ...

J'ai supposé, naturellement, que le dossier où mon script PHP stockait les téléchargements de fichiers temporaires était /tmp. Cette croyance a été renforcée par le fait que les echo sys_get_temp_dir() . PHP_EOL;rendements /tmp. En outre, echo ini_get('upload_tmp_dir');ne retourne rien.

Pour vérifier que le fichier téléchargé apparaît en fait brièvement dans mon /tmpdossier, j'ai ajouté une sleep(30);déclaration à mon script (comme suggéré ici ) et ai navigué vers mon /tmpdossier dans cPanel File Manager pour localiser le fichier. Cependant, quoi qu'il arrive, le fichier téléchargé ne s'y trouvait nulle part.

J'ai passé des heures à essayer de déterminer la raison de cela et à mettre en œuvre toutes les suggestions proposées ici.

Enfin, après avoir recherché les fichiers de mon site Web pour la requête tmp, j'ai découvert que mon site contenait d'autres dossiers nommés tmpdans différents répertoires. J'ai réalisé que mon script PHP écrivait en fait les fichiers téléchargés .cagefs/tmp. (Le paramètre «Afficher les fichiers cachés» doit être activé dans cPanel pour afficher ce dossier.)

Alors, pourquoi la sys_get_temp_dirfonction renvoie-t-elle des informations inexactes?

Voici une explication de la page Web PHP.net pour sys_get_temp_dir(c'est-à-dire le commentaire principal):

Si elle est exécutée sur un système Linux où systemd a PrivateTmp = true (qui est la valeur par défaut sur CentOS 7 et peut-être d'autres distributions plus récentes), cette fonction renverra simplement "/ tmp", et non le chemin vrai, beaucoup plus long et quelque peu dynamique.

Cet article SO approfondit également le problème:

Grillons
la source
0

J'ai eu le même problème et aucun thème n'était mon erreur. Archivez votre fichier .htaccess, si vous en avez un, si "MultiViews" est activé. J'ai dû les désactiver.

Murolack
la source
0

J'ai eu un problème similaire et le problème était de mauvaise valeur dans htaccess, comme l'a mentionné shamittomar.

Changer php_value post_max_size 10MBpourphp_value post_max_size 10M

Johnny Vietnam
la source
0

J'étais vide $_FILESparce qu'après avoir <form enctype="multipart/form-data" method="post">placé

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

Le code initial était comme

<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>

J'ai décidé de modifier et

<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>

La conclusion est donc qu'après <form enctype="multipart/form-data" method="post">doit être <input name, type, idet ne doit pas être <div>ou d'autres balises

Dans ma situation, le code correct était

<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
la source
0

J'ai aussi eu des problèmes avec $ _FILES empty. La check-list ci-dessus ne mentionne pas MultiViews dans .htaccess, httpd.conf ou httpd-vhost.conf.

Si vous avez défini MultiViews dans la directive options pour votre répertoire contenant le site Web, $ _FILES sera vide, même si l'en-tête Content-Length indique que le fichier a été téléchargé.

gerteb
la source
0

Si vous utilisez JQuery Mobile

L'utilisation d'un formulaire en plusieurs parties avec une entrée de fichier n'est pas prise en charge par Ajax. Dans ce cas, vous devez décorer le formulaire parent avec data-ajax = "false" pour vous assurer que le formulaire est correctement soumis au serveur.

<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
la source
0

Détachez votre formulaire de la page que vous utilisez dans une simple page php qui n'a que le formulaire et le code php, et testez-le comme ça.

Tout script d'amorçage ou java peut nettoyer le _FILES []. C'était mon cas

user2195463
la source