Skip to content

How PHP handles files

Greg Bowler edited this page Apr 25, 2024 · 5 revisions

PHP's $_FILES array is inconsistent when working with single versus multiple file uploads. This library normalises the behaviour and provides one interface to work with.

To upload a file, the HTML form needs to have two attributes: method="post" and enctype="multipart/form-data". Then any <input> with the type=file attribute will be sent to the server in a way that PHP understands.

There are two ways to upload multiple files at once:

  1. Have more than one file upload input in the same form.
  2. Have a field with the multiple attribute.

(or a combination of both).

Example form with a single file input:

<form method="post" enctype="multipart/form-data">
	<input type="file" name="exampleFile" />
	<button>Submit</button>
</form>

When submitted, PHP's $_FILES array will contain something like this:

$_FILES = [
	"exampleFile" => [
		"name" => "Clouds.jpg",
		"type" => "image/jpeg",
		"tmp_name" => "/tmp/phpgt/input/" . uniqid() . ".tmp",
		"error" => 0,
		"size" => 1234,
	]
];

An example of a form with multiple file inputs:

<form method="post" enctype="multipart/form-data">
	<input type="file" name="exampleFile1" />
	<input type="file" name="exampleFile2" />
	<input type="file" name="exampleFile3" />

	<button>Submit more than one file</button>
</form>

When submitted with just two files, PHP's $_FILES array will contain something like this:

array (size=3)
  'exampleFile1' => 
    array (size=5)
      'name' => string 'Clouds.jpg' (length=10)
      'type' => string 'image/jpeg' (length=10)
      'tmp_name' => string '/tmp/php97F5.tmp' (length=45)
      'error' => int 0
      'size' => int 1481681
  'exampleFile2' => 
    array (size=5)
      'name' => string 'Mountains.jpg' (length=13)
      'type' => string 'image/jpeg' (length=10)
      'tmp_name' => string '/tmp/php9806.tmp' (length=45)
      'error' => int 0
      'size' => int 263091
  'exampleFile3' => 
    array (size=5)
      'name' => string '' (length=0)
      'type' => string '' (length=0)
      'tmp_name' => string '' (length=0)
      'error' => int 4
      'size' => int 0

Finally, an example of a form with a single multiple file input:

<form method="post" enctype="multipart/form-data">
	<input type="file" name="exampleMultipleFile[]" multiple />
	<button>Submit</button>
</form>

Note the use of square brackets in the name attribute. This is required to work with multiple files (or any other multiple input).

When submitted with two files, PHP's $_FILES array will contain something like this:

array (size=1)
  'exampleMultipleFile' => 
    array (size=5)
      'name' => 
        array (size=2)
          0 => string 'Clouds.jpg' (length=10)
          1 => string 'Mountains.jpg' (length=13)
      'type' => 
        array (size=2)
          0 => string 'image/jpeg' (length=10)
          1 => string 'image/jpeg' (length=10)
      'tmp_name' => 
        array (size=2)
          0 => string 'C:\Users\g105b\AppData\Local\Temp\php537B.tmp' (length=45)
          1 => string 'C:\Users\g105b\AppData\Local\Temp\php538C.tmp' (length=45)
      'error' => 
        array (size=2)
          0 => int 0
          1 => int 0
      'size' => 
        array (size=2)
          0 => int 1481681
          1 => int 263091

This data structure is inconsistent with the others and would require different PHP logic to handle file inputs when the multiple attribute is used. Using PHP.Gt/Input normalises this data structure into a predictable interface, whether there's 0, 1, or many files in the HTTP message.

Clone this wiki locally