Dlaczego $ _FILES miałoby być puste podczas przesyłania plików do PHP?

145

Mam zainstalowany WampServer 2 na moim komputerze z systemem Windows 7. Używam Apache 2.2.11 i PHP 5.2.11. Kiedy próbuję załadować dowolny plik z formularza, wydaje się, że ładuje się, ale w PHP $_FILEStablica jest pusta. W c:\wamp\tmpfolderze nie ma pliku . Skonfigurowałem php.inizezwalanie na przesyłanie plików i tym podobne. tmpFolderu przeczytał przywileje / zapisu dla bieżącego użytkownika. Jestem zdumiony.

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
źródło
2
Czy sprawdziłeś dzienniki błędów?
Byron Whitlock
Jestem pewien, że jest coś głupiego, czego nie dostrzegasz. Na przykład, czy na pewno masz kod vanilla-upload.php?
Luca Matteis
Ha, miałem ten sam problem. Sprawdziłem dzienniki błędów i okazało się, że przesyłany jest plik, który przekracza maksymalny dozwolony rozmiar.
BrightIntelDusk

Odpowiedzi:

493

Oto lista kontrolna do przesyłania plików w PHP:

  1. Sprawdź php.ini pod kątem:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M

    • Być może będziesz musiał użyć .htaccesslub .user.inijeśli korzystasz z hostingu współdzielonego i nie masz do niego dostępu php.ini.
    • Upewnij się, że edytujesz poprawny plik ini - użyj phpinfo()funkcji, aby sprawdzić, czy ustawienia są faktycznie stosowane.
    • Również upewnić się, że nie wpisana błędnie rozmiary - powinien być 100M nie 100MB .
  2. Upewnij się, że <form>tag ma enctype="multipart/form-data"atrybut. Żaden inny tag nie będzie działał, musi to być tag FORMULARZA. Dokładnie sprawdź, czy jest wpisany poprawnie . Dokładnie sprawdź, czy dane wieloczęściowe / formularze są otoczone prostymi cudzysłowami, a nie inteligentnymi cudzysłowami wklejonymi z Worda LUB z bloga na stronie internetowej (WordPress konwertuje proste cudzysłowy na cudzysłowy pod kątem!). Jeśli masz wiele formularzy na stronie, upewnij się, że oba mają ten atrybut. Wpisz je ręcznie lub wypróbuj proste pojedyncze cudzysłowy wpisywane ręcznie.

  3. Upewnij się, że nie masz dwóch pól pliku wejściowego z tym samym nameatrybutem. Jeśli potrzebujesz obsługiwać wiele, umieść nawiasy kwadratowe na końcu nazwy:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
  4. Upewnij się, że katalogi tmp i upload mają ustawione poprawne uprawnienia do odczytu i zapisu. Tymczasowy folder przesyłania jest określony w ustawieniach PHP jako upload_tmp_dir.

  5. Upewnij się, że miejsce docelowe pliku i katalogi tmp / upload nie zawierają spacji.

  6. Upewnij się, że wszystkie <form>pozycje na Twojej stronie mają </form>zamknięte tagi.

  7. Upewnij się, że tag FORMULARZA ma method="POST". Żądania GET nie obsługują przesyłania danych wieloczęściowych / formularzy.

  8. Upewnij się, że znacznik wejściowy pliku ma atrybut NAME. Atrybut ID NIE jest wystarczający! Atrybuty ID są używane w DOM, a nie w ładunkach POST.

  9. Upewnij się, że nie używasz Javascript do wyłączenia <input type="file">pola podczas przesyłania

  10. Upewnij się, że nie zagnieżdżasz form takich jak <form><form></form></form>

  11. Sprawdź strukturę HTML pod kątem nieprawidłowych / nakładających się tagów, takich jak <div><form></div></form>

  12. Upewnij się również, że przesyłany plik nie zawiera żadnych znaków innych niż alfanumeryczne.

  13. Kiedyś spędziłem godziny, próbując zrozumieć, dlaczego tak się nagle stało. Okazało się, że zmodyfikowałem niektóre ustawienia PHP w programie .htaccess, a jedno z nich (jeszcze nie wiem, które) powodowało niepowodzenie przesyłania i $_FILESbyło puste.

  14. Możesz potencjalnie spróbować uniknąć podkreślenia ( _) w name=""atrybucie <input>tagu

  15. Spróbuj przesłać bardzo małe pliki, aby zawęzić, czy jest to problem z rozmiarem pliku.

  16. Sprawdź dostępne miejsce na dysku. Chociaż jest to bardzo rzadkie, jest wspomniane w komentarzu do strony podręcznika PHP :

    Jeśli tablica $ _FILES nagle stanie się tajemniczo pusta, nawet jeśli twój formularz wydaje się poprawny, powinieneś sprawdzić miejsce na dysku dostępne dla twojej tymczasowej partycji folderu. W mojej instalacji wszystkie przesyłanie plików nie powiodło się bez ostrzeżenia. Po wielu zgrzytaniu zębami próbowałem zwolnić dodatkowe miejsce, po czym przesyłanie plików nagle znowu zadziałało.

  17. Upewnij się, że nie przesyłasz formularza za pośrednictwem żądania AJAX POST zamiast zwykłego żądania POST, które powoduje ponowne załadowanie strony. Przeszedłem przez każdy punkt powyższej listy i w końcu dowiedziałem się, że powodem, dla którego moja zmienna $ _FILES była pusta, było przesyłanie formularza za pomocą żądania AJAX POST. Wiem, że istnieją metody przesyłania plików przy użyciu Ajax, ale może to być ważny powód, dla którego tablica $ _FILES jest pusta.

Źródło niektórych z tych punktów:
http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

shamittomar
źródło
12
Być może „zaakceptowana” odpowiedź rozwiązała oryginalny post, ale ta odpowiedź jest najbardziej pomocna. W razie wątpliwości spójrz na źródło widziane przez przeglądarkę. Zaznaczając każdą pozycję na tej liście i śledząc wstecz, znalazłem swój błąd w najbardziej nieoczekiwanym miejscu. Jeśli zmagasz się z podobnym problemem, uwierz mi, prawdopodobnie nie jest to błąd w Apache. ;)
quickthyme
3
Upewnij się również, że element formularza zawierający dane wejściowe NIE jest elementem podrzędnym innego elementu formularza. np.<form><form><input type="file"></form></form>
sudee
3
łał! dziękuję za tę listę. mój problem był nr 2. dzwoniłem $('#my-form')[0].reset();w obsłudze przesyłania.
Gavin
2
dzięki. w moim przypadku numer 7. przyczyną był enctype = „multipart / form-data”.
Thupten
3
Koleś, jesteś ratownikiem. Spędziłem godziny, próbując to rozgryźć (2) był mój problem ... Dzięki!
Mike Q
74

Jeśli chodzi o HTML, wydaje się, że poprawnie ustawiłeś tę część. Masz jużenctype="multipart/form-data" co jest bardzo ważne w formularzu.

Jeśli chodzi o php.inikonfigurację, czasami w systemach php.iniistnieje wiele plików. Upewnij się, że edytujesz właściwy. Wiem, że powiedziałeś, że skonfigurowałeś swój php.iniplik do przesyłania plików, ale czy ustawiłeś również swój upload_max_filesizei post_max_sizebył większy niż plik, który próbujesz przesłać? Więc powinieneś mieć:

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

Czy Twój katalog: "c:\wamp\tmp"ma uprawnienia do odczytu i zapisu? Czy pamiętałeś o ponownym uruchomieniu Apache po wprowadzeniu php.inizmian?


Brian
źródło
4
+1: Wskazówka dotycząca ponownego uruchomienia serwera Apache. Wielu użytkowników systemu Windows o tym zapomina.
shamittomar
36

Ważne jest, aby dodać enctype="multipart/form-data"do swojego formularza przykład

<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
źródło
14

Dziękuję wszystkim za różnorodne wyczerpujące odpowiedzi. To wszystko jest bardzo pomocne. Odpowiedź okazała się czymś bardzo dziwnym. Okazuje się, że PHP 5.2.11 nie lubi:

post_max_size = 2G

lub

post_max_size = 2048M

Jeśli zmienię to na 2047M, przesyłanie działa.

elmonty
źródło
17
Zauważ, że tak wysoka wartość jest podatnością na ataki typu out-of-space / ddos. Wystarczy dodać to, aby ludzie zdawali sobie sprawę, że to za dużo, gdy próbują skopiować i wkleić Twoje rozwiązanie. W każdym razie 2 koncerty wymagałyby zbyt długiego czasu przesyłania.
Manuel Arwed Schmidt
Już nie za duży. Mamy klientów, którzy dość regularnie przesyłają pliki z zakresu 1-3G. Ponieważ przesyłają pliki na swoje własne serwery i znajdują się na białej liście adresów IP, wymiana jest całkiem normalna i jest jedynie sposobem na umożliwienie klientowi korzystania ze swojego sprzętu w taki sposób, w jaki chce go używać. Płacą rachunki, bez ryzyka związanego z bezpieczeństwem, bez problemów.
TheSatinKnight,
8

Mam ten sam problem, patrząc na 2 godziny, jest bardzo proste, aby najpierw sprawdzić konfigurację naszego serwera.

Przykład:

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

każdy typ rozmiaru pliku to :20mb, ale nasz upload_max_sizejest powyżej, 20mbale tablica jest null. Odpowiedź brzmi: nasze post_max_sizepowinno być większe niż upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
shashik493
źródło
6

Oto kolejna przyczyna, którą znalazłem: Podczas korzystania z JQuery Mobile i atrybutu formularza data-ajax jest ustawiony na true, tablica FILES będzie pusta. Więc ustaw data-ajax na false.

mat711
źródło
5

Upewnij się, że element wejściowy ma atrybut „nazwa”. <input type="file" name="uploadedfile" />

Jeśli tego nie ma, $ _FILES będzie puste.

Adrian Parr
źródło
4

Zmagałem się z tym samym problemem i wszystko testowałem, nie otrzymywałem raportów o błędach i nic nie wydawało się być w porządku. Miałem error_reporting (E_ALL) Ale nagle zdałem sobie sprawę, że nie sprawdziłem dziennika Apache i voilà! Wystąpił błąd składni w skrypcie ...! (brakujące „}”)

Więc chociaż jest to coś oczywistego do sprawdzenia, można o tym zapomnieć ... W moim przypadku (linux) jest to:

/var/log/apache2/error.log
Luis Rosety
źródło
3

Nikt o tym nie wspomniał, ale pomogło mi to i niewiele miejsc w sieci o tym wspomina.

Upewnij się, że Twój php.ini ustawia następujący klucz:

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

Jeśli chcesz, abyś używał bezwzględnej ścieżki do pliku serwera, musisz skontaktować się z usługodawcą hostingowym. Powinieneś być w stanie zobaczyć inne przykłady katalogów w pliku php.ini, aby to ustalić. Jak tylko to ustawię, otrzymałem wartości w moim obiekcie _FILES.

Na koniec upewnij się, że twój folder tmp i wszędzie tam, gdzie przenosisz pliki, mają odpowiednie uprawnienia, aby można je było odczytywać i zapisywać.

AaronP
źródło
2

Jeśli próbujesz przesłać tablicę plików to może trzeba zwiększyć max_file_uploadsw php.iniktórym jest domyślnie ustawiony na20

Uwaga : max_file_uploadsNIE można tego zmienić poza php.ini. Zobacz „Błąd” PHP # 50684

Tahir Yasin
źródło
2

Innym możliwym winowajcą są przekierowania Apache. W moim przypadku skonfigurowałem httpd.conf apache tak, aby przekierowywał niektóre strony w naszej witrynie do wersji http, a inne strony do wersji https strony, jeśli jeszcze nie były. Strona, na której miałem formularz z plikiem wejściowym, była jedną ze stron skonfigurowanych do wymuszania ssl, ale strona wyznaczona jako akcja formularza została skonfigurowana jako http. Tak więc strona przesłałaby przesyłkę do wersji ssl strony akcji, ale apache przekierowywał ją do wersji http strony, a dane postu, w tym przesłany plik, zostały utracone.

user2723315
źródło
2

Sprawdź swój php.ini pod kątem enable_post_data_reading = On , ponieważ:

Wyłączenie tej opcji powoduje, że $ _POST i $ _FILES nie są wypełniane . Jedynym sposobem na odczytanie postdata będzie wtedy opakowanie strumienia wejściowego php: //. (...)

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

jmng
źródło
1

Jeśli twój główny skrypt jest http://Some_long_URL/index.phpostrożny, podaj pełny adres URL (z wyraźnym index.phpi nie tylko http://Some_long_URL) w actionpolu. Zaskakujące jest to, że jeśli nie, wykonywany jest właściwy skrypt, ale z pustą wartością en $ _FILES!

Gibbie
źródło
1

Natknąłem się na ten sam problem i stwierdziłem, że to moje IDE było częścią problemu. Uruchamiałem debugger bezpośrednio z IDE (PHPStorm) zamiast po prostu używać przeglądarki bezpośrednio. URL wygenerowany przez IDE wyglądał następująco:

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

i po prostu używając:

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

działało dobrze. Moja konfiguracja to PC / Windows 10 / WAMPSERVER 3.0.6 64bit

Marc M.
źródło
to samo, jak dotąd biegałem w kółko przez godzinę! dzięki
EKanadily
1

Nie ufaj lokalizacji folderu tymczasowego dostarczonej przez sys_get_temp_dir jeśli jesteś we współdzielonym środowisku hostingu.

Oto jeszcze jedna rzecz do sprawdzenia, o której jeszcze nie wspomniano ...

Oczywiście założyłem, że folder, w którym mój skrypt PHP przechowuje tymczasowe przesłane pliki, to folder /tmp. To przekonanie zostało wzmocnione faktem, że echo sys_get_temp_dir() . PHP_EOL;powraca /tmp. Również,echo ini_get('upload_tmp_dir'); nic nie zwraca.

Aby sprawdzić, czy przesłany plik faktycznie pojawia się na krótko w moim /tmpfolderze, dodałem sleep(30);oświadczenie do mojego skryptu (zgodnie z sugestią tutaj ) i przeszedłem do mojego/tmp folderu w cPanel File Manager, aby zlokalizować plik. Jednak bez względu na wszystko przesłanego pliku nigdzie nie było.

Spędziłem godziny, próbując ustalić przyczynę takiego stanu rzeczy, i wdrożyłem każdą sugestię, która została tu przedstawiona.

Wreszcie, po przeszukaniu plików mojej witryny pod kątem zapytania tmp, odkryłem, że moja witryna zawiera inne foldery nazwane tmpw innych katalogach. Zdałem sobie sprawę, że mój skrypt PHP faktycznie zapisuje przesłane pliki do .cagefs/tmp. ( „Pokaż ukryte pliki” Aby wyświetlić ten folder, ustawienie musi być włączone w cPanel).

Dlaczego więc sys_get_temp_dirfunkcja zwraca niedokładne informacje?

Oto wyjaśnienie ze strony PHP.net dla sys_get_temp_dir(tj. Najwyższy komentarz):

Jeśli działa w systemie Linux, w którym systemd ma PrivateTmp = true (co jest wartością domyślną w CentOS 7 i być może w innych nowszych dystrybucjach), ta funkcja zwróci po prostu „/ tmp”, a nie prawdziwą, znacznie dłuższą, nieco dynamiczną ścieżkę.

Ten post dotyczący SO zagłębia się również w problem:

Świerszcze
źródło
0

Mam ten sam problem i żaden z motywów nie był moim błędem. Sprawdź swój plik .htaccess, jeśli go masz, jeśli „MultiViews” jest włączone. Musiałem je wyłączyć.

Murolack
źródło
0

Miałem podobny problem i problem miał niewłaściwą wartość w htaccess, jak wspomniał shamittomar.

Zmień php_value post_max_size 10MBnaphp_value post_max_size 10M

Johnny Vietnam
źródło
0

Byłem pusty, $_FILESponieważ po <form enctype="multipart/form-data" method="post">umieszczeniu

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

Początkowy kod był podobny

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

Postanowiłem zmodyfikować i

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

Tak więc wniosek jest taki, że after <form enctype="multipart/form-data" method="post">musi być <input name, type, idi nie może być <div>lub jakieś inne tagi

W mojej sytuacji poprawny kod to

<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
źródło
0

Ja też miałem problemy z pustymi plikami $ _FILES. Powyższa lista kontrolna nie wspomina o wielu widokach w .htaccess, httpd.conf lub httpd-vhost.conf.

Jeśli masz ustawione MultiViews w dyrektywie options dla twojego katalogu zawierającego witrynę internetową, $ _FILES będzie puste, nawet jeśli nagłówek Content-Length pokazuje, że przesłany przeze mnie plik.

gerteb
źródło
0

Jeśli używasz JQuery Mobile

Używanie formularza wieloczęściowego z plikiem wejściowym nie jest obsługiwane przez Ajax. W takim przypadku powinieneś udekorować formularz nadrzędny danymi data-ajax = "false", aby upewnić się, że formularz został poprawnie przesłany na serwer.

<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
źródło
0

Odłącz swój formularz od strony, której używasz, do prostej strony php, która zawiera tylko formularz i kod php, i przetestuj go w ten sposób.

Każdy skrypt bootstrap lub java może wyczyścić _FILES []. To był mój przypadek

user2195463
źródło