Warum sollte $ _FILES beim Hochladen von Dateien auf PHP leer sein?

145

Ich habe WampServer 2 auf meinem Windows 7-Computer installiert. Ich verwende Apache 2.2.11 und PHP 5.2.11. Wenn ich versuche, eine Datei aus einem Formular hochzuladen, scheint sie hochzuladen, aber in PHP ist das $_FILESArray leer. Der c:\wamp\tmpOrdner enthält keine Datei . Ich habe konfiguriert php.ini, um das Hochladen von Dateien und dergleichen zuzulassen. Der tmpOrdner verfügt über Lese- / Schreibrechte für den aktuellen Benutzer. Ich bin ratlos.

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
quelle
2
Haben Sie die Fehlerprotokolle überprüft?
Byron Whitlock
Ich bin sicher, es gibt etwas Dummes, das Sie übersehen. Sind Sie zum Beispiel sicher, dass Sie den Code haben vanilla-upload.php?
Luca Matteis
Ha ich hatte das gleiche Problem. Ich habe die Fehlerprotokolle überprüft und festgestellt, dass eine Datei hochgeladen wurde, die die maximal zulässige Größe überschreitet.
BrightIntelDusk

Antworten:

493

Hier ist eine Checkliste für das Hochladen von Dateien in PHP:

  1. Überprüfen Sie php.ini für:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Möglicherweise müssen Sie verwenden .htaccessoder .user.iniwenn Sie auf Shared Hosting sind und keinen Zugriff darauf haben php.ini.
    • Stellen Sie sicher, dass Sie die richtige INI-Datei bearbeiten. Verwenden Sie die phpinfo()Funktion, um zu überprüfen, ob Ihre Einstellungen tatsächlich angewendet werden.
    • Stellen Sie außerdem sicher, dass Sie die Größen nicht falsch schreiben - dies sollte 100M nicht der Fall sein 100MB.
  2. Stellen Sie sicher, dass Ihr <form>Tag das enctype="multipart/form-data"Attribut hat. Kein anderes Tag funktioniert, es muss Ihr FORM-Tag sein. Stellen Sie sicher, dass die Schreibweise korrekt ist . Stellen Sie sicher, dass mehrteilige / Formulardaten von GERADEN ANGEBOTEN umgeben sind, nicht von intelligenten Anführungszeichen, die aus Word oder einem Website-Blog eingefügt wurden (WordPress konvertiert gerade Anführungszeichen in Anführungszeichen!). Wenn Sie mehrere Formulare auf der Seite haben, stellen Sie sicher, dass beide dieses Attribut haben. Geben Sie sie manuell ein oder versuchen Sie es mit einfachen einfachen Anführungszeichen, die manuell eingegeben werden.

  3. Stellen Sie sicher, dass Sie nicht zwei Eingabedateifelder mit demselben nameAttribut haben. Wenn Sie mehrere unterstützen müssen, setzen Sie eckige Klammern am Ende des Namens:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Stellen Sie sicher, dass für Ihre tmp- und Upload-Verzeichnisse die richtigen Lese- und Schreibberechtigungen festgelegt sind. Der temporäre Upload-Ordner wird in den PHP-Einstellungen als angegeben upload_tmp_dir.

  5. Stellen Sie sicher, dass Ihr Dateiziel und Ihre tmp / upload-Verzeichnisse keine Leerzeichen enthalten.

  6. Stellen Sie sicher, dass alle <form>auf Ihrer Seite </form>enge Tags haben.

  7. Stellen Sie sicher, dass Ihr FORM-Tag hat method="POST". GET-Anforderungen unterstützen keine Uploads von Mehrteil- / Formulardaten.

  8. Stellen Sie sicher, dass Ihr Dateieingabe-Tag ein NAME-Attribut hat. Ein ID-Attribut ist NICHT ausreichend! ID-Attribute werden im DOM verwendet, nicht für POST-Nutzdaten.

  9. Stellen Sie sicher, dass Sie kein Javascript verwenden, um Ihr <input type="file">Feld bei der Übermittlung zu deaktivieren

  10. Stellen Sie sicher, dass Sie keine Formulare wie verschachteln <form><form></form></form>

  11. Überprüfen Sie Ihre HTML-Struktur auf ungültige / überlappende Tags wie <div><form></div></form>

  12. Stellen Sie außerdem sicher, dass die Datei, die Sie hochladen, keine nicht alphanumerischen Zeichen enthält.

  13. Einmal habe ich nur stundenlang versucht herauszufinden, warum mir das plötzlich passiert ist. Es stellte sich heraus, dass ich einige der PHP-Einstellungen in geändert .htaccesshatte und eine davon (noch nicht sicher, welche) dazu führte, dass der Upload fehlschlug und $_FILESleer war.

  14. Sie könnten möglicherweise versuchen, Unterstriche ( _) im name=""Attribut des <input>Tags zu vermeiden

  15. Versuchen Sie, sehr kleine Dateien hochzuladen, um einzugrenzen, ob es sich um ein Problem mit der Dateigröße handelt.

  16. Überprüfen Sie Ihren verfügbaren Speicherplatz. Obwohl sehr selten, wird es in diesem PHP-Handbuch Seite Kommentar erwähnt :

    Wenn das Array $ _FILES plötzlich auf mysteriöse Weise leer wird, obwohl Ihr Formular korrekt erscheint, sollten Sie den verfügbaren Speicherplatz für Ihre temporäre Ordnerpartition überprüfen. In meiner Installation sind alle Datei-Uploads ohne Warnung fehlgeschlagen. Nach langem Zähneknirschen habe ich versucht, zusätzlichen Speicherplatz freizugeben, woraufhin das Hochladen von Dateien plötzlich wieder funktionierte.

  17. Stellen Sie sicher, dass Sie das Formular nicht über eine AJAX-POST-Anforderung senden, sondern über eine normale POST-Anforderung, bei der eine Seite neu geladen wird. Ich ging jeden Punkt in der obigen Liste durch und fand schließlich heraus, dass der Grund, aus dem meine Variable $ _FILES leer war, darin bestand, dass ich das Formular mit einer AJAX POST-Anfrage abschickte. Ich weiß, dass es Methoden gibt, um Dateien auch mit Ajax hochzuladen, aber dies könnte ein gültiger Grund sein, warum Ihr $ _FILES-Array leer ist.

Quelle für einige dieser Punkte:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

Shamittomar
quelle
12
Vielleicht hat die "akzeptierte" Antwort den ursprünglichen Beitrag gelöst, aber diese Antwort fand ich am hilfreichsten. Sehen Sie sich im Zweifelsfall die Quelle an, die vom Browser angezeigt wird. Ich habe jedes Element in dieser Liste abgehakt und rückwärts verfolgt und meinen Fehler an einer höchst unerwarteten Stelle gefunden. Wenn Sie mit einem ähnlichen Problem zu kämpfen haben, glauben Sie mir, es ist wahrscheinlich kein Fehler in Apache. ;)
Quickthyme
3
Stellen Sie außerdem sicher, dass Ihr Formularelement, das die Dateieingabe enthält, KEIN untergeordnetes Element eines anderen Formularelements ist. zB<form><form><input type="file"></form></form>
sudee
3
Beeindruckend! Danke für diese Liste. Mein Problem war # 2. Ich habe $('#my-form')[0].reset();den Submit-Handler angerufen .
Gavin
2
Vielen Dank. in meinem Fall Nummer 7. enctype = "multipart / form-data" war der Schuldige.
Thupten
3
DUDE, du bist ein Lebensretter. Ich verbringe Stunden damit, dies herauszufinden (2) war mein Problem ... Danke!
Mike Q
74

In Bezug auf den HTML-Code scheinen Sie diesen Teil korrekt eingerichtet zu haben. Sie haben bereits das, enctype="multipart/form-data"was auf dem Formular sehr wichtig ist.

In Bezug auf Ihr php.iniSetup sind auf Systemen manchmal mehrere php.iniDateien vorhanden. Stellen Sie sicher, dass Sie die richtige bearbeiten. Ich weiß , Sie sagen , Sie Ihre konfigurierten php.iniDatei - Datei - Uploads, haben , aber haben Sie auch Ihre gesetzt upload_max_filesizeund post_max_sizegrößer zu sein als die Datei , die Sie laden wollen? Sie sollten also haben:

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

Verfügt Ihr Verzeichnis "c:\wamp\tmp"über Lese- und Schreibberechtigungen? Haben Sie daran gedacht, Apache neu zu starten, nachdem Sie die php.iniÄnderungen vorgenommen haben?


Brian
quelle
4
+1: Zum Neustart von Apache Server Tipp. Viele Windows-Benutzer vergessen das.
Shamittomar
36

Es ist wichtig enctype="multipart/form-data", Ihrem Formular ein Beispiel hinzuzufügen

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

Vielen Dank an alle für die unterschiedlich umfassenden Antworten. Das sind alle sehr hilfreich. Die Antwort stellte sich als etwas sehr Seltsames heraus. Es stellt sich heraus, dass PHP 5.2.11 Folgendes nicht mag:

post_max_size = 2G

oder

post_max_size = 2048M

Wenn ich es ändere 2047M, funktioniert der Upload.

Elmonty
quelle
17
Beachten Sie, dass ein so hoher Wert eine Anfälligkeit für Angriffe außerhalb des Weltraums / ddos ​​darstellt. Fügen Sie dies einfach hinzu, damit die Leute wissen, dass es zu viel ist, wenn sie versuchen, Ihre Lösung zu kopieren und einzufügen. Wie auch immer, 2 Gigs würden eine viel zu lange Upload-Zeit erfordern.
Manuel Arwed Schmidt
Nicht mehr zu groß. Wir haben Kunden, die regelmäßig Dateien im Bereich 1-3G hochladen. Da sie Dateien auf ihre eigenen Server hochladen und IP-Whitelist-Server sind, ist der Austausch ganz normal und lediglich eine Möglichkeit, einem Client zu ermöglichen, ihre Geräte so zu verwenden, wie sie sie verwenden möchten. Sie bezahlen die Rechnungen, kein Sicherheitsrisiko, keine Probleme.
TheSatinKnight
8

Ich habe das gleiche Problem 2 Stunden suchen, ist sehr einfach, wir überprüfen zuerst unsere Serverkonfiguration.

Beispiel:

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

Jede Art von Dateigröße ist :20mb, aber unsere upload_max_sizeist oben, 20mbaber Array ist null. Die Antwort ist, dass unsere post_max_sizegrößer sein sollte als upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
shashik493
quelle
6

Hier eine weitere Ursache, die ich gefunden habe: Wenn Sie JQuery Mobile verwenden und das Formularattribut data-ajax auf true gesetzt ist, ist das FILES-Array leer. Setzen Sie also data-ajax auf false.

Schachmatt711
quelle
5

Stellen Sie sicher, dass Ihr Eingabeelement ein Attribut 'name' hat. <input type="file" name="uploadedfile" />

Wenn dies fehlt, sind die $ _FILES leer.

Adrian Parr
quelle
4

Ich hatte mit dem gleichen Problem zu kämpfen und alles zu testen, keine Fehlerberichterstattung zu erhalten und nichts schien falsch zu sein. Ich hatte error_reporting (E_ALL) Aber plötzlich wurde mir klar, dass ich das Apache-Protokoll und voilà nicht überprüft hatte! Es gab einen Syntaxfehler im Skript ...! (ein fehlendes "}")

Obwohl dies offensichtlich überprüft werden muss, kann es vergessen werden ... In meinem Fall (Linux) ist es bei:

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

Niemand erwähnte dies, aber es half mir und nicht viele Stellen im Netz erwähnen es.

Stellen Sie sicher, dass Ihre php.ini den folgenden Schlüssel setzt:

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

Sie müssen sich bei Ihrem Webhost erkundigen, ob Sie einen absoluten Server-Dateipfad verwenden sollen. Sie sollten in der Lage sein, andere Verzeichnisbeispiele in Ihrer php.ini-Datei zu sehen, um dies festzustellen. Sobald ich es eingestellt habe, habe ich Werte in meinem _FILES-Objekt.

Stellen Sie schließlich sicher, dass Ihr tmp-Ordner und überall dort, wo Sie Dateien verschieben, die richtigen Berechtigungen haben, damit sie gelesen und beschrieben werden können.

AaronP
quelle
2

Wenn Sie eine Reihe von Dateien hochladen möchten , dann müssen Sie unter Umständen erhöhen max_file_uploadsin php.inidem standardmäßig eingestellt ist20

Hinweis : max_file_uploadskann NICHT außerhalb von php.ini geändert werden. Siehe PHP "Bug" # 50684

Tahir Yasin
quelle
2

Ein weiterer möglicher Schuldiger sind Apache-Weiterleitungen. In meinem Fall hatte ich die httpd.conf von Apache eingerichtet, um bestimmte Seiten unserer Website auf http-Versionen und andere Seiten auf https-Versionen der Seite umzuleiten, sofern dies nicht bereits geschehen war. Die Seite, auf der ich ein Formular mit einer Dateieingabe hatte, war eine der Seiten, die zum Erzwingen von SSL konfiguriert waren, aber die Seite, die als Aktion des Formulars festgelegt wurde, wurde als http konfiguriert. Die Seite übermittelte den Upload also an die SSL-Version der Aktionsseite, aber Apache leitete ihn an die http-Version der Seite weiter, und die Post-Daten, einschließlich der hochgeladenen Datei, gingen verloren.

user2723315
quelle
2

Überprüfen Sie Ihre php.ini auf enable_post_data_reading = On , weil:

Wenn Sie diese Option deaktivieren, werden $ _POST und $ _FILES nicht ausgefüllt . Die einzige Möglichkeit, Postdaten zu lesen, besteht dann im PHP: // Input Stream Wrapper. (...)

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

jmng
quelle
1

Wenn Ihr Hauptskript http://Some_long_URL/index.phpsorgfältig ist, geben Sie die vollständige URL (explizit index.phpund nicht nur http://Some_long_URL) in das actionFeld ein. Wenn nicht, wird überraschenderweise das richtige Skript ausgeführt, jedoch mit en leeren $ _FILES!

Gibbie
quelle
1

Ich bin auf dasselbe Problem gestoßen und habe festgestellt, dass meine IDE Teil des Problems war. Ich habe den Debugger direkt von der IDE (PHPStorm) aus gestartet, anstatt nur den Browser direkt zu verwenden. Die von der IDE erzeugte URL lautete wie folgt:

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

und nur mit:

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

hat gut funktioniert. Mein Setup ist PC / Windows 10 / WAMPSERVER 3.0.6 64bit

Marc M.
quelle
das gleiche hier, ich lief bisher eine Stunde im Kreis! danke
EKanadily
1

Vertrauen Sie nicht dem Speicherort des temporären Ordners, der von angegeben wird, sys_get_temp_dirwenn Sie sich in einer gemeinsam genutzten Hosting-Umgebung befinden.

Hier ist noch eine Sache zu überprüfen, die noch nicht erwähnt wurde ...

Ich nahm natürlich an, dass der Ordner, in dem mein PHP-Skript temporäre Datei-Uploads gespeichert hatte, war /tmp. Dieser Glaube wurde durch die Tatsache verstärkt, dass echo sys_get_temp_dir() . PHP_EOL;zurückkehrt /tmp. Auch echo ini_get('upload_tmp_dir');gibt nichts zurück.

Um zu überprüfen, ob die hochgeladene Datei tatsächlich kurz in meinem /tmpOrdner angezeigt wird, habe ich sleep(30);meinem Skript eine Anweisung hinzugefügt (wie hier vorgeschlagen ) und /tmpim cPanel-Dateimanager zu meinem Ordner navigiert , um die Datei zu suchen. Unabhängig davon war die hochgeladene Datei dort nirgends zu finden.

Ich habe stundenlang versucht, den Grund dafür zu ermitteln, und jeden hier angebotenen Vorschlag umgesetzt.

Nachdem ich meine Website-Dateien nach der Abfrage durchsucht hatte tmp, stellte ich schließlich fest, dass meine Website andere Ordner enthielt, die tmpin verschiedenen Verzeichnissen benannt waren. Ich stellte fest, dass mein PHP-Skript tatsächlich die hochgeladenen Dateien in schrieb .cagefs/tmp. (Die Einstellung "Versteckte Dateien anzeigen " muss in cPanel aktiviert sein, damit dieser Ordner angezeigt werden kann.)

Warum gibt die sys_get_temp_dirFunktion ungenaue Informationen zurück?

Hier ist eine Erklärung von der PHP.net-Webseite für sys_get_temp_dir(dh den obersten Kommentar):

Wenn auf einem Linux-System mit systemd PrivateTmp = true ausgeführt wird (dies ist die Standardeinstellung unter CentOS 7 und möglicherweise anderen neueren Distributionen), gibt diese Funktion einfach "/ tmp" zurück, nicht den wahren, viel längeren, etwas dynamischen Pfad.

Dieser SO-Beitrag befasst sich auch mit dem Thema:

Grillen
quelle
0

Ich habe das gleiche Problem und keines der Themen war mein Fehler. Checken Sie in Ihrer .htaccess-Datei ein, falls Sie eine haben, und aktivieren Sie "MultiViews". Ich musste sie deaktivieren.

Murolack
quelle
0

Ich hatte ein ähnliches Problem und das Problem hatte im htaccess einen falschen Wert, wie Shamittomar erwähnte.

Wechseln Sie php_value post_max_size 10MBzuphp_value post_max_size 10M

Johnny Vietnam
quelle
0

Ich war leer, $_FILESweil nach dem <form enctype="multipart/form-data" method="post">Platzieren

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

Der ursprüngliche Code war wie

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

Ich entschied mich zu modifizieren und

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

Die Schlussfolgerung ist also, dass nach <form enctype="multipart/form-data" method="post">muss <input name, type, idund darf nicht <div>oder einige andere Tags sein

In meiner Situation war der richtige Code

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

Ich hatte auch Probleme mit $ _FILES leer. In der obigen Checkliste werden MultiViews in .htaccess, httpd.conf oder httpd-vhost.conf nicht erwähnt.

Wenn Sie MultiViews in der Optionsanweisung für Ihr Verzeichnis mit der Website festgelegt haben, ist $ _FILES leer, obwohl der Header "Content-Length" angezeigt wird, wenn die von mir hochgeladene Datei angezeigt wird.

gerteb
quelle
0

Wenn Sie JQuery Mobile verwenden

Die Verwendung eines mehrteiligen Formulars mit einer Dateieingabe wird von Ajax nicht unterstützt. In diesem Fall sollten Sie das übergeordnete Formular mit data-ajax = "false" dekorieren, um sicherzustellen, dass das Formular ordnungsgemäß an den Server gesendet wird.

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

Trennen Sie Ihr Formular von der Seite, die Sie verwenden, in eine einfache PHP-Seite, die nur das Formular und den PHP-Code enthält, und testen Sie es so.

Jedes Bootstrap- oder Java-Skript kann die _FILES [] bereinigen. Das war mein Fall

user2195463
quelle