web-dev-qa-db-fra.com

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

WampServer 2 est installé sur mon ordinateur Windows 7. J'utilise Apache 2.2.11 et PHP 5.2.11. Lorsque je tente de télécharger un fichier à partir d'un formulaire, il semble que ce soit le cas, mais en PHP, le tableau $_FILES est vide. Il n'y a pas de fichier dans le dossier c:\wamp\tmp. J'ai configuré php.ini pour permettre le téléchargement de fichiers et autres. Le dossier tmp 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";
?>
118
elmonty

Merci à tous pour la variété des réponses complètes. Ce sont tous très utiles. 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.

14
elmonty

Voici une check-list 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 .htaccess ou .user.ini si vous utilisez un hébergement partagé et n'avez pas accès à php.ini.
    • Assurez-vous que vous modifiez le fichier ini correct. Utilisez la fonction phpinfo() pour vérifier que vos paramètres .__ sont bien appliqués. 
    • Assurez-vous également de ne pas mal orthographier les tailles. __ devrait être 100Mpas100MB.
  2. Assurez-vous que votre balise <form> a l'attribut enctype="multipart/form-data". Aucune autre balise ne fonctionnera, il doit s'agir de votre balise FORM. Vérifiez bien qu'il est orthographié correctement. Vérifiez que multipart/form-data est entouré de citations droites, et non de citations intelligentes collées à partir de Word OR depuis 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. Tapez-les manuellement ou essayez des guillemets simples droits tapés manuellement.

  3. Assurez-vous de ne pas avoir deux champs de fichier d'entrée avec le même attribut name. Si vous avez besoin de prendre en charge plusieurs éléments, mettez les 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 possèdent le jeu d'autorisations de lecture et d'écriture correct. Le dossier de téléchargement temporaire est spécifié dans les paramètres PHP en tant que upload_tmp_dir.

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

  6. Assurez-vous que tous les <form>s de votre page ont des balises fermées </form>.

  7. Assurez-vous que votre balise FORM a method="POST". Les demandes GET ne prennent pas en charge les téléchargements multipart/form-data.

  8. Assurez-vous que votre balise d’entrée de fichier a un attribut NAME. Un attribut ID n'est pas suffisant! Les attributs d'ID sont destinés à être utilisés dans le DOM, pas pour les données utiles POST.

  9. Assurez-vous de ne pas utiliser Javascript pour désactiver votre champ <input type="file"> lors de l'envoi.

  10. Assurez-vous de ne pas imbriquer de formulaires tels que <form><form></form></form>

  11. Vérifiez votre structure HTML pour les balises invalides/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 à coup. Il s’est avéré que j’avais modifié certains des paramètres PHP dans .htaccess, et l’un d’eux (qui ne savait pas encore lequel) faisait échouer le téléchargement et $_FILES était vide.

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

  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 PHP Commentaire de page de manuel :

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

  17. Assurez-vous de ne pas soumettre le formulaire via une demande AJAX POST au lieu d'une demande normale POST qui entraîne 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 à l'aide d'une demande AJAX POST. Je sais qu'il existe aussi 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-mysteriously-empty/

414
shamittomar

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

En ce qui concerne votre configuration php.ini, il existe parfois plusieurs systèmes php.ini sur des systèmes. Assurez-vous d’éditer le bon. Je sais que vous avez dit que vous avez configuré votre fichier php.ini pour le téléchargement de fichiers, mais avez-vous également défini vos upload_max_filesize et post_max_size pour qu'ils soient plus volumineux que le fichier que vous essayez de télécharger? Donc vous devriez 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 à la fois des autorisations de lecture et d'écriture? Avez-vous pensé à redémarrer Apache après avoir apporté les modifications php.ini?


67
Brian

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

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.

5
dutchman711

J'ai un même problème à la recherche de 2 heures, il 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');   

n'importe quel type de fichier a la taille :20mb, mais notre upload_max_size est supérieur à 20mb mais le tableau est null. La réponse est que notre post_max_size devrait être supérieur à upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
5
shashik493

Je me débattais avec le même problème et je testais tout, je n’obtenais pas de rapport d’erreur et rien ne semblait se tromper ..__J'ai eu un rapport d’erreur (E_ALL) __. Il y avait une erreur de syntaxe sur le script ...! (un "}" manquant)

Donc, même s’il est évident que c’est une chose à vérifier, il peut être oublié ....

/var/log/Apache2/error.log
3
Luis Rosety

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

Si cela manque, $ _FILES sera vide.

3
Adrian Parr

Les redirections Apache sont un autre coupable possible. Dans mon cas, le fichier httpd.conf d’Apache a été configuré pour rediriger certaines pages de notre site vers les versions http et d’autres pages vers les versions https de la page, si ce n’était déjà fait. 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 étant 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.

2
user2723315

Si vous essayez de charger un tableau de fichiers, vous devrez peut-être augmenter max_file_uploads in php.ini qui est défini par défaut sur 20

Note: max_file_uploads NE peut PAS être changé en dehors de php.ini. Voir PHP "Bug" # 50684

2
Tahir Yasin

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

La désactivation de cette option provoque que $ _POST et $ _FILES ne soient pas renseignés. Le seul moyen de lire les données postérieures sera alors via l'encapsuleur de flux d'entrée php: //. (...)

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

2
jmng

Personne n'en a parlé mais cela m'a aidé et peu d'endroits sur le net en ont parlé.

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 de 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 eu des valeurs dans mon objet _FILES.

Enfin, assurez-vous que votre dossier tmp et les fichiers que vous déplacez disposent des autorisations appropriées pour pouvoir être lus et écrits.

2
AaronP

J'ai rencontré le même problème et j'ai découvert que c'était mon IDE qui faisait partie du problème. Je lançais le débogueur directement à partir de IDE (PHPStorm) au lieu d'utiliser directement le navigateur. L'URL générée IDE ressemblait à ceci:

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

et juste en utilisant:

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

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

1
Marc M.

Ne faites pas confiance à l'emplacement du dossier temporaire fourni par _sys_get_temp_dir_ si 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 dans lequel mon script PHP stockait les téléchargements de fichiers temporaires était _/tmp_. Cette croyance a été renforcée par le fait que echo sys_get_temp_dir() . PHP_EOL; renvoie _/tmp_. De plus, echo ini_get('upload_tmp_dir'); ne renvoie rien.

Pour vérifier que le fichier téléchargé apparaît effectivement dans mon dossier _/tmp_, j'ai ajouté une instruction sleep(30); à mon script (comme suggéré ici ) et j'ai accédé à mon _/tmp_ dans cPanel File Manager pour localiser le fichier. Quoi qu'il en soit, le fichier téléchargé n'y était nulle part.

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

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

Alors, pourquoi la fonction _sys_get_temp_dir_ 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 le plus élevé):

Si fonctionnant 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 vrai chemin, beaucoup plus long et quelque peu dynamique.

Cet article SO approfondit également la question:

1
Crickets

J'ai eu le même problème et le problème était dans la mauvaise valeur dans htaccess comme Shamittomar l'a mentionné.

Remplacez php_value post_max_size 10MB par php_value post_max_size 10M

0
Johnny Vietnam

Si vous utilisez JQuery Mobile

L'utilisation d'un formulaire multipart 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 envoyé 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>
0
Rajan

J'étais vide $_FILES car après <form enctype="multipart/form-data" method="post"> j'ai 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>

Donc, la conclusion est qu’après <form enctype="multipart/form-data" method="post"> doit être <input name, type, id et 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>
0
Andris

J'ai eu le même problème et aucun des thèmes n'était mon erreur. Vérifiez votre fichier .htaccess, si vous en avez un, si les "MultiViews" sont activées. Je devais les désactiver.

0
Murolack

Si votre script principal est http://Some_long_URL/index.php, veillez à spécifier l’URL complète (avec index.php explicite et pas uniquement http://Some_long_URL) dans le champ action. Étonnamment, sinon, le bon script est exécuté, mais avec en $ vide _FILES!

0
Gibbie

Moi aussi j'ai eu des problèmes avec $ _FILES vide. La liste de contrôle ci-dessus ne mentionne pas MultiViews dans .htaccess, httpd.conf ou httpd-vhost.conf.

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

0
gerteb