172

I have WampServer 2 installed on my Windows 7 computer. I'm using Apache 2.2.11 and PHP 5.2.11. When I attempt to upload any file from a form, it seems to upload, but in PHP, the $_FILES array is empty. There is no file in the c:\wamp\tmp folder. I have configured php.ini to allow file uploads and such. The tmp folder has read/write privileges for the current user. I'm stumped.

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";
?>
Nikola K.
  • 7,093
  • 13
  • 31
  • 39
elmonty
  • 2,395
  • 3
  • 20
  • 28
  • 2
    Have you checked the error logs? – Byron Whitlock Aug 27 '10 at 18:04
  • I'm sure there something dumb that you're overlooking. For example, are you sure to have the code in `vanilla-upload.php`? – Luca Matteis Aug 27 '10 at 18:07
  • Ha I was having the same problem. I checked the error logs and it said that a file was being uploaded that exceeded the maximum allowed size. – BrightIntelDusk Mar 04 '14 at 00:44
  • 1
    Ha, my `` had no `name=` :D – Fanky Sep 02 '21 at 12:38
  • I tried to upload a file not from root, but with a script that was located in a "subfolder", like this: www.something.com\somthing_\something.php. $_FILE was empty! I tried the same code from www.something.com - and it worked... no clue how to solve this.. I did workaround. – Andr Jul 06 '23 at 06:20
  • I dont belive I lose hours just because the input(s) had no name... thanks @Fanky – ZEE Aug 29 '23 at 19:43

22 Answers22

578

Here's a check-list for file uploading in PHP:

  1. Check php.ini for:
    file_uploads = On
    post_max_size = 100M
    upload_max_filesize = 100M
  • You might need to use .htaccess or .user.ini if you are on shared hosting and don't have access to php.ini.
  • Make sure you’re editing the correct ini file – use the phpinfo() function to verify your settings are actually being applied.
  • Also make sure you don’t misspell the sizes - it should be 100M not 100MB.
  1. Make sure your <form> tag has the enctype="multipart/form-data" attribute. No other tag will work, it has to be your FORM tag. Double check that it is spelled correctly. Double check that multipart/form-data is surrounded by STRAIGHT QUOTES, not smart quotes pasted in from Word OR from a website blog (WordPress converts straight quotes to angle quotes!). If you have multiple forms on the page, make sure they both have this attribute. Type them in manually, or try straight single quotes typed in manually.

  2. Make sure you do not have two input file fields with the same name attribute. If you need to support multiple, put square brackets at the end of the name:

    <input type="file" name="files[]">
    <input type="file" name="files[]">
    
  3. Make sure your tmp and upload directories have the correct read+write permissions set. The temporary upload folder is specified in PHP settings as upload_tmp_dir.

  4. Make sure your file destination and tmp/upload directories do not have spaces in them.

  5. Make sure all <form>'s on your page have </form> close tags.

  6. Make sure your FORM tag has method="POST". GET requests do not support multipart/form-data uploads.

  7. Make sure your file input tag has a NAME attribute. An ID attribute is NOT sufficient! ID attributes are for use in the DOM, not for POST payloads.

  8. Make sure you are not using Javascript to disable your <input type="file"> field on submission

  9. Make sure you're not nesting forms like <form><form></form></form>

  10. Check your HTML structure for invalid/overlapping tags like <div><form></div></form>

  11. Also make sure that the file you are uploading does not have any non-alphanumeric characters in it.

  12. Once, I just spent hours trying to figure out why this was happening to me all of a sudden. It turned out that I had modified some of the PHP settings in .htaccess, and one of them (not sure which yet) was causing the upload to fail and $_FILES to be empty.

  13. You could potentially try avoiding underscores (_) in the name="" attribute of the <input> tag

  14. Try uploading very small files to narrow down whether it's a file-size issue.

  15. Check your available disk space. Although very rare, it is mentioned in this PHP Manual page comment:

    If the $_FILES array suddenly goes mysteriously empty, even though your form seems correct, you should check the disk space available for your temporary folder partition. In my installation, all file uploads failed without warning. After much gnashing of teeth, I tried freeing up additional space, after which file uploads suddenly worked again.

  16. Be sure that you're not submitting the form through an AJAX POST request instead of a normal POST request that causes a page to reload. I went through each and every point in the list above, and finally found out that the reason due to which my $_FILES variable was empty was that I was submitting the form using an AJAX POST request. I know that there are methods to upload files using ajax too, but this could be a valid reason why your $_FILES array is empty.

Source for some of these points:
https://web.archive.org/web/20050426084124/http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/

Skeets
  • 4,476
  • 2
  • 41
  • 67
shamittomar
  • 46,210
  • 12
  • 74
  • 78
  • 1
    This doesn't apply to the discussion starter, but I had hosting provider who had their firewall policy too strict which caused some uploads to fail. – The Pixel Developer Aug 29 '10 at 15:51
  • 19
    Maybe the "accepted" answer solved the original post, but this answer is the one that I found most helpful. When in doubt, look at the source as seen by the browser. Checking off each item in this list and tracing backward, I found my error in a most unexpected place. If you're struggling with a similar problem, believe me, it's probably not a bug in Apache. ;) – quickthyme Jan 25 '12 at 05:26
  • 4
    Also make sure your form element containing the file input is NOT a child of another form element. e.g. `
    `
    – sudee Aug 14 '13 at 12:32
  • 3
    wow! thank you for this list. my problem was #2. i was calling `$('#my-form')[0].reset();` in the submit handler. – Gavin Oct 26 '13 at 05:06
  • I'd add that certain Suhosin configurations can throw uploads off, and I'm not convinced that "_" in an upload field is a cause for concern. Otherwise, thanks for the exhaustive answer! Good reference. – Chris Burgess Mar 11 '14 at 10:09
  • Another point : replacing ` – Fractaliste Jun 10 '14 at 08:33
  • 5
    thanks. in my case number 7 . enctype="multipart/form-data" was the culprit. – Thupten Aug 21 '14 at 04:37
  • 1
    Some of these are from an article here: http://getluky.net/2004/10/04/apachephp-_files-array-mysteriously-empty/ copy and pasted without attribution – Antony D'Andrea Feb 12 '15 at 15:21
  • Also check that this php.ini key is set, if it is blank it will result in a blank $_FILES object: `upload_tmp_dir="/path/to/tmp/dir/"` – AaronP Apr 08 '15 at 21:48
  • #8 was the one that hit me! I thought files only needed IDs, not names! – tetris11 Jan 20 '16 at 17:56
  • In my situation - where I had to enable cross domain uploading - I had to add "cache-control" to the Access-Control-Allow-Headers header. – Dawied Mar 17 '16 at 16:03
  • Make sure all attributes are enclosed properly within quotes. In my case the form worked well, but $_FILES was still empty, because I missed a quote in the form. – Markus Zeller Jun 06 '16 at 15:43
  • what if i have all steps in place and it uploads the file but at some company places the $_files stays empty.. How to debug this one? – Nuri Ensing Sep 13 '16 at 12:19
  • Also, check php.ini for enable_post_data_reading=On , because "Disabling this option causes $_POST and $_FILES not to be populated." (http://php.net/manual/en/ini.core.php#ini.enable-post-data-reading) – jmng Jul 18 '17 at 10:03
  • I had to start my local Xampp for Windows with administration rights ...guess thats #4, but just in case someone is looking for this – micha Nov 29 '18 at 23:17
  • "enctype="multipart/form-data", why is this bit mandatory ? anyways solved the issue for me thanks – Benoit F Feb 12 '20 at 09:44
  • One more thing to the list if you are using php-fpm: - Once you change values in /etc/php.ini you must restart php-fpm service in order to take the new values -> systemctl restart php-fpm - An just in case also restart you httpd service -> systemctl restart httpd – Harry244 Oct 22 '20 at 14:21
  • @sudee thanks dude! mine is not working because my input file is inside a div tag, it works after i remove the div and move the input file tag directly inside the form tag – prs_wjy Jan 17 '21 at 00:22
  • This link solved my requirement. https://www.a2hosting.com/kb/developer-corner/php/using-php-directives-in-custom-htaccess-files/setting-the-php-maximum-upload-file-size-in-an-htaccess-file I added the following to my htaccess as suggested. `php_value upload_max_filesize nnM` and `php_value post_max_size nnM` – DanimalReks Apr 19 '21 at 15:05
81

As far as the HTML you appear to have set that part up correctly. You already have the enctype="multipart/form-data" which is very important to have on the form.

As far as your php.ini setup, sometimes on systems multiple php.ini files exist. Be sure you are editing the correct one. I know you said you have configured your php.ini file to have file uploads, but did you also set your upload_max_filesize and post_max_size to be larger than the file you are trying to upload? So you should have:

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

Does your directory: "c:\wamp\tmp" have both read and write permissions? Did you remember to restart Apache after you made the php.ini changes?


pierre
  • 49
  • 6
Brian
  • 1,035
  • 6
  • 14
41

It is important to add enctype="multipart/form-data" to your form, example

<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
  • 45,103
  • 14
  • 92
  • 122
16

Thank you everybody for the vary comprehensive replies. Those are all very helpful. The answer turned out to be something very odd. It turns out that PHP 5.2.11 doesn't like the following:

post_max_size = 2G

or

post_max_size = 2048M

If I change it to 2047M, the upload works.

Nikola K.
  • 7,093
  • 13
  • 31
  • 39
elmonty
  • 2,395
  • 3
  • 20
  • 28
  • 18
    Note that such a high value is an vulnerability to out-of-space/ddos attacks. Just adding this so people are aware its too much, when they try to copy&paste your solution. Anyways, 2 gigs would require an upload time that is way too long. – Manuel Arwed Schmidt Jun 24 '14 at 20:17
  • 2
    Not too large any more. We have clients who upload files in the 1-3G range quite regularly. Since they are uploading files onto their own servers, and they are IP whitelisted servers, the exchange is quite normal and merely a way to allow a client to use their equipment the way they want to use it. They pay the bills, no security risk involved, no problems. – TheSatinKnight Jul 23 '17 at 07:35
9

I have a same problem looking 2 hours ,is very simple to we check our server configuration first.

Example:

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

any type of file size is :20mb, but our upload_max_size is above 20mb but array is null. Answer is our post_max_size should be greater than upload_max_filesize

post_max_size = 750M  
upload_max_filesize = 750M
Rasclatt
  • 12,498
  • 3
  • 25
  • 33
shashik493
  • 790
  • 1
  • 10
  • 12
8

Make sure your input element has a 'name' attribute. <input type="file" name="uploadedfile" />

If this is missing the $_FILES will be empty.

Adrian Parr
  • 81
  • 1
  • 2
6

Here another cause I found: When using JQuery Mobile and the form attribute data-ajax is set to true, the FILES array will be empty. So set data-ajax to false.

checkmate711
  • 3,301
  • 2
  • 35
  • 45
6

No one mentioned this but it helped me out and not many places on the net mention it.

Make sure your php.ini sets the following key:

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

You'll need to check with your webhost if they want you to use an absolute server file path. You should be able to see other directory examples in your php.ini file to determine this. As soon as I set it I got values in my _FILES object.

Finally make sure that your tmp folder and wherever you are moving files to have the correct permissions so that they can be read and written to.

AaronP
  • 196
  • 2
  • 11
  • This fixed my problem. In my case the temp directory was in C drive and it looks like XAMPP didn't have permission to write in C drive. I changed the temp dir to some folder in D drive and that worked. – Adil Malik Jun 01 '21 at 18:01
5

I was struggling with the same problem and testing everything, not getting error reporting and nothing seemed to be wrong. I had error_reporting(E_ALL) But suddenly I realized that I had not checked the apache log and voilà! There was a syntax error on the script...! (a missing "}" )

So, even though this is something evident to be checked, it can be forgotten... In my case (linux) it is at:

/var/log/apache2/error.log
Luis Rosety
  • 396
  • 4
  • 10
3

Check your php.ini for enable_post_data_reading=On , because:

Disabling this option causes $_POST and $_FILES not to be populated. The only way to read postdata will then be through the php://input stream wrapper. (... )

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

jmng
  • 2,479
  • 1
  • 25
  • 38
2

If you are trying to upload an array of files then you may need to increase max_file_uploads in php.ini which is by default set to 20

Note: max_file_uploads can NOT be changed outside php.ini. See PHP "Bug" #50684

Tahir Yasin
  • 11,489
  • 5
  • 42
  • 59
2

Another possible culprit is apache redirects. In my case I had apache's httpd.conf set up to redirect certain pages on our site to http versions, and other pages to https versions of the page, if they weren't already. The page on which I had a form with a file input was one of the pages configured to force ssl, but the page designated as the action of the form was configured to be http. So the page would submit the upload to the ssl version of the action page, but apache was redirecting it to the http version of the page and the post data, including the uploaded file was lost.

2

If your main script is http://Some_long_URL/index.php be carefull to specify the full URL (with explicit index.php and not only http://Some_long_URL) in the action field. Surprisingly, if not, the right script is executed, but with en empty $_FILES !

Gibbie
  • 21
  • 1
2

Do not trust the temp folder location provided by sys_get_temp_dir if you're in a shared hosting environment.

Here is one more thing to check that has not yet been mentioned...

I assumed, naturally, that the folder where my PHP script stored temporary file uploads was /tmp. This belief was reinforced by the fact that echo sys_get_temp_dir() . PHP_EOL; returns/tmp. Also, echo ini_get('upload_tmp_dir'); returns nothing.

To verify that the uploaded file does in fact briefly appear in my /tmp folder, I added a sleep(30); statement to my script (as suggested here) and navigated to my /tmp folder in cPanel File Manager to locate the file. However, no matter what, the uploaded file was nowhere to be found there.

I spent hours trying to determine the reason for this, and implemented every suggestion that's been offered here.

Finally, after searching my website files for the query tmp, I discovered that my site contained other folders named tmp in different directories. I realized that my PHP script was actually writing the uploaded files to .cagefs/tmp. (The "Show Hidden Files" setting must be enabled in cPanel in order to view this folder.)

So, why does the sys_get_temp_dir function return inaccurate info?

Here's an explanation from the PHP.net webpage for sys_get_temp_dir (i.e., the top comment):

If running on a Linux system where systemd has PrivateTmp=true (which is the default on CentOS 7 and perhaps other newer distros), this function will simply return "/tmp", not the true, much longer, somewhat dynamic path.

This SO post delves into the issue, as well:

Crickets
  • 524
  • 1
  • 8
  • 23
1

I ran into the same issue and found that it was my IDE was part of the issue. I was launching the debugger directly from the IDE (PHPStorm) instead of just using the browser directly. The IDE spawned URL was like this:

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

and just using:

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

worked just fine. My set up is PC / Windows 10 / WAMPSERVER 3.0.6 64bit

Marc M.
  • 166
  • 1
  • 8
0

I got the same problem and none of theme was my error. Check in your .htaccess file, if you got one, if "MultiViews" are enabled. I had to disable them.

Murolack
  • 1,897
  • 1
  • 14
  • 17
0

I had similar problem and the issue was in wrong value in htaccess as shamittomar mentioned.

Change php_value post_max_size 10MB to php_value post_max_size 10M

Carl0s1z
  • 4,683
  • 7
  • 32
  • 47
Johnny Vietnam
  • 196
  • 1
  • 6
0

I was empty $_FILES because after <form enctype="multipart/form-data" method="post"> i placed

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

Initial code was like

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

I decided to modify and

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

So conclusion is that after <form enctype="multipart/form-data" method="post"> must be <input name, type, id and must not be <div> or some other tags

In my situation correct code was

<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
  • 1,434
  • 1
  • 19
  • 34
0

I too had problems with $_FILES empty. The above check-list do not mention MultiViews in .htaccess, httpd.conf or httpd-vhost.conf.

If you have MultiViews set in the options directive for your directory containing the web site, $_FILES will be empty, even though Content-Length header if showing that the file i uploaded.

gerteb
  • 1
0

If you are using JQuery Mobile

Using a multipart form with a file input is not supported by Ajax. In this case you should decorate the parent form with data-ajax="false" to ensure the form is submitted properly to the server.

<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
  • 43
  • 7
0

Detach your form form the page you-re using into a simple php page that has the form and php code only, and test it like that.

Any bootstrap or java script might clean out the _FILES[]. That was my case

user2195463
  • 321
  • 5
  • 8
0

If you're using AJAX instead of a Form submission, then ensure the request header Content-Type is set to multipart/form-data; boundary=myAwesomeBoundary' where myAwesomeBoundary is the unique string that separates the request body parts. I made the mistake of overriding the Content-Type header by setting it to only multipart/form-data without setting the boundary. The fix was to not override the header but let the browser generate it for me.

Jacob
  • 2,212
  • 1
  • 12
  • 18