Multipart forms

  • Web interfaces postal services, which allow you to add an attachment (attach) to a letter, and to do this you must first upload the file to the server, and only after that it can be added to the letter;
  • Interactive photo galleries and photo albums that cannot exist without a mechanism for uploading files to the server;
  • Free software portals used for file sharing various programs, etc.

Uploading a file to the server is carried out using a multipart form, which has a file upload field. The enctype parameter is set to multipart/form-data :



This is what the given multipart form will look like (you can try using it to see the result of the multipart forms by uploading a file small size to server):

Multipart forms typically use the POST submission method. As can be seen from the previous example, this form has two fields:

  • File selection field for uploading ;
  • Field for specifying the file name that it will have on the server .

Processing multipart forms

Before you start writing a script for processing a multipart form, you need to edit the configuration file php.ini to allow files to be uploaded to the server.

Configuration PHP file php.ini has three parameters related to uploading files to the server:

  • file_uploads=On - allows files to be uploaded to the server via HTTP;
  • upload_tmp_dir=/tmp - sets the directory for temporary storage of uploaded files;
  • upload_max_filesize=2M - sets the maximum size of uploaded files.

If your web server is running under operating system Linux systems, then you need to restart the service:

service httpd restart

How does PHP handle multipart forms? Once it receives the file, it saves it in a temporary directory called upload_tmp_dir , with the file name chosen at random. It then creates four superglobal array variables $_FILES . This array contains information about the downloaded file.

The variables defined for uploaded files depend on PHP versions and current configuration. The superglobal array $_FILES is available since PHP 4.1.0. In case the register_globals configuration directive is set to on, additionally variables with appropriate names will be declared. As of version 4.2.0, the default value for the register_globals option is off.

The contents of the $_FILES array for our example are shown below. Note that this assumes the name uploadfile is used for the file selection field, as per the multipart form above. Of course, the field name can be anything.

  • $_FILES["uploadfile"]["name"] - the name of the file before it is sent to the server, for example, pict.gif;
  • $_FILES["uploadfile"]["size"] - size of the received file in bytes;
  • $_FILES["uploadfile"]["type"] - MIME type of the received file (if the browser was able to detect it), for example: image/gif, image/png, image/jpeg, text/html;
  • (that’s what we called the file upload field) - contains the name of the file in the temporary directory, for example: /tmp/phpV3b3qY;
  • $_FILES["uploadfile"]["error"] - Error code that may occur when downloading a file. Key ["error"] was added in PHP 4.2.0. You can see the corresponding error codes

After the script completes, the temporary file will be deleted. This means that we must copy it to another location before the script completes. That is, the algorithm for the script to upload a file to the server is as follows:

If the "Submit" button is pressed, the file will already be uploaded to the server and its name will be in the $_FILES["uploadfile"]["name"] variable. In this case, the script should immediately copy a file named $_FILES["uploadfile"]["tmp_name"] to some directory (write rights to this directory are required).

The file is copied using the function copy() :

Only use the copy() copy function, not the move function, because:

  • The temporary file will be deleted automatically;
  • If the temporary directory is on other media, an error message will be displayed.

Let's say we need to upload a file to the uploads directory, which is located in root directory web server (in the DocumentRoot directory).

// Let's create a directory just in case. If he already created,
// we won't see an error message because we'll use the @ operator:

@mkdir("uploads", 0777);

// Copy the file from /tmp to uploads
// The file name will be the same as before sending to the server:

Copy($_FILES["uploadfile"]["tmp_name"],"uploads/".basename($_FILES["uploadfile"]["name"]));

On Linux, everything is much more complicated - we need to take into account the permissions of the uploads directory. Most likely in this case, the function mkdir() won't work because we don't have write permission to the DocumentRoot directory (usually /var/www/html or /home/httpd/html). Log in as root, create an uploads directory, and change its owner and permissions as follows:

// Create the uploads directory

// Set the apache owner name and its group - also apache:

Chown apache:apache uploads

// Allow everyone to write (777) + set the sticky bit (1):

Chmod 1777 uploads

The file size can be limited; if desired, you can edit the .htaccess file and limit access to the uploads directory - specify either specific users who can access the directory, or IP addresses.

Now you can upload files to the server.

We write PHP script uploading files to the server


// Directory where we will receive the file:
$uploaddir = "./files/" ;
$uploadfile = $uploaddir . basename($_FILES["uploadfile"]["name"]);

// Copy the file from the directory for temporary storage of files:
if (copy ($ _FILES [ "uploadfile" ][ "tmp_name" ], $uploadfile ))
{
echo "

The file was successfully uploaded to the server

" ;
}
else ( echo "

Error! Failed to upload file to server!

"
; exit ; )

// Display information about the downloaded file:
echo "

Information about the file uploaded to the server:

"
;
echo "

Original name of the uploaded file: ".$ _FILES [ "uploadfile" ][ "name" ]. "

" ;
echo "

Mime type of the uploaded file: ".$ _FILES [ "uploadfile" ][ "type" ]. "

" ;
echo "

Uploaded file size in bytes: ".$ _FILES [ "uploadfile" ][ "size" ]. "

" ;
echo "

Temporary file name: ".$ _FILES [ "uploadfile" ][ "tmp_name" ]. "

" ;

?>

Loading multiple files can be implemented using, for example, different name values ​​for the input tag.

It is also possible to automatically obtain information organized into an array about several simultaneously downloaded files. To implement this feature, use the same syntax for submitting an array from an HTML form as for multiple select and checkbox fields:


Send these files:






If such a form was submitted, the $_FILES["userfile"] , $_FILES["userfile"]["name"] , and $_FILES["userfile"]["size"] arrays will be initialized (in the same way , like $HTTP_POST_FILES for PHP 4.1.0 and earlier). If the register_globals configuration directive is set to on , the accompanying global variables will also be initialized. Each of these variables will be a numerically indexed array of corresponding values ​​for the received files.

Let's assume that the files /home/test/some.html and /home/test/file.bin were loaded. In this case, the $_FILES["userfile"]["name"] variable will have the value some.html , and the $_FILES["userfile"]["name"] variable will have the value file.bin . Likewise, the variable $_FILES["userfile"]["size"] will contain the size of the some.html file and so on.

Variables $_FILES["userfile"]["name"] , $_FILES["userfile"]["tmp_name"], $_FILES["userfile"]["size"] and $_FILES["userfile"]["type"] will also be initialized.

Conclusion:

As you can see, organizing file uploads to the server is not that difficult. It is more difficult to ensure the required level of security, since uploading files to the server can be used by attackers to attack the server. For information on how to ensure the required level of security when working with Uploads, see.



<<< Назад Content Forward >>>
If you have any other questions or something is not clear - welcome to our

Multiple files can be uploaded using different name for input.

It is also possible to upload multiple files simultaneously and have the information organized automatically in arrays for you. To do so, you need to use the same array submission syntax in the HTML form as you do with multiple selects and checkboxes:

Send these files:


Warning

As of PHP 5.2.12, the max_file_uploads configuration setting acts as a limit on the number of files that can be uploaded in one request. You will need to ensure that your form does not try to upload more files in one request than this limit.

14 years ago

When uploading multiple files, the $_FILES variable is created in the form:

Array
=> Array
=> foo.txt
=> bar.txt
)

=> Array
=> text/plain
=> text/plain
)

=> Array
=> /tmp/phpYzdqkD
=> /tmp/phpeEwEWG
)

=> Array
=> 0
=> 0
)

=> Array
=> 123
=> 456
)

I found it made for a little cleaner code if I had the uploaded files array in the form

Array
=> Array
=> foo.txt
=> text/plain
=> /tmp/phpYzdqkD
=> 0
=> 123
)

=> Array
=> bar.txt
=> text/plain
=> /tmp/phpeEwEWG
=> 0
=> 456
)

I wrote a quick function that would convert the $_FILES array to the cleaner (IMHO) array.

Function reArrayFiles (& $file_post ) (

$file_ary = array();
$file_count = count($file_post["name"]);
$file_keys = array_keys($file_post);

For ($i = 0; $i< $file_count ; $i ++) {
foreach ($file_keys as $key) (
$file_ary [ $i ][ $key ] = $file_post [ $key ][ $i ];
}
}

Return $file_ary ;
}

?>

Now I can do the following:

If($_FILES["upload"]) (
$file_ary = reArrayFiles($_FILES["ufile"]);

Foreach ($file_ary as $file) (
print "File Name: " . $file["name"];
print "File Type: " . $file["type"];
print "File Size: " . $file["size"];
}
}

?>

5 years ago

This is also needed for elements.

So, if you have an input element like this:

This should be written as

else you"ll only be able to get one of the files.

9 years ago

Here is a function to fix the indicators of a multi-dimensional for easier parsing when dealing with file uploads. It takes a single $_FILES field array as a parameter and separates each individual uploaded file by numeric key. This allows for iterating like:

fixFilesArray($_FILES["array_of_files"]);
foreach ($_FILES [ "array_of_files" ] as $position => $file ) (
// should output array with indices name, type, tmp_name, error, size
var_dump($file);
}
?>

Here's the code:

/**
* Fixes the odd indexing of multiple file uploads from the format:
*
* $_FILES["field"]["key"]["index"]
*
* To the more standard and appropriate:
*
* $_FILES["field"]["index"]["key"]
*
* @param array $files
* @author Corey Ballou
* @link http://www.jqueryin.com
*/
function fixFilesArray (& $files )
{
$names = array("name" => 1 , "type" => 1 , "tmp_name" => 1 , "error" => 1 , "size" => 1 );

Foreach ($files as $key => $part ) (
// only deal with valid keys and multiple files
$key = (string) $key ;
if (isset($names [ $key ]) && is_array ($part )) (
foreach ($part as $position => $value ) (
$files [ $position ][ $key ] = $value ;
}
// remove old key reference
unset($files [ $key ]);
}
}
}
?>

3 years ago

This is a very simple example:





Document









echo "

"
;
$img = $_FILES["img"];

if(!empty($img ))
{
$img_desc = reArrayFiles($img);
print_r($img_desc);

Foreach($img_desc as $val )
{
$newname = date("YmdHis" , time()). mt_rand(). ".jpg" ;
move_uploaded_file ($val [ "tmp_name" ], "./uploads/" . $newname );
}
}

function reArrayFiles ($file)
{
$file_ary = array();
$file_count = count($file["name"]);
$file_key = array_keys($file);

For($i = 0 ; $i< $file_count ; $i ++)
{
foreach($file_key as $val)
{
$file_ary [ $i ][ $val ] = $file [ $val ][ $i ];
}
}
return $file_ary ;
}

2 years ago

Once I had to do a maintenance in a huge ERP that had several multiple upload inputs inside an array. Just like this:







The $_FILES array is created like this:

Array
=> Array
=> Array
=> teste.c
=> teste
)

=> Array
=> text/x-csrc
=> application/octet-stream
)

=> Array
=> /opt/lampp/temp/phpuf3KNj
=> /opt/lampp/temp/php0yPZap
)

=> Array
=> 0
=> 0
)

=> Array
=> 1960
=> 8661
)

=> Array
=> Array
=> jefrey.html
=> notas.txt
)

=> Array
=> text/html
=> text/plain
)

=> Array
=> /opt/lampp/temp/php87nfyu
=> /opt/lampp/temp/phpUBlvVz
)

=> Array
=> 0
=> 0
)

=> Array
=> 583
=> 191
)

I"ve managed to re-arrange this array like this:

Array
=> Array
=> Array
=> teste.c
=> text/x-csrc
=> /opt/lampp/temp/phpuf3KNj
=> 0
=> 1960
)

=> Array
=> teste
=> application/octet-stream
=> /opt/lampp/temp/php0yPZap
=> 0
=> 8661
)

=> Array
=> Array
=> jefrey.html
=> text/html
=> /opt/lampp/temp/php87nfyu
=> 0
=> 583
)

=> Array
=> notas.txt
=> text/plain
=> /opt/lampp/temp/phpUBlvVz
=> 0
=> 191
)

Here's my snippet:
function reArrayFilesMultiple (& $files ) (
$uploads = array();
foreach($_FILES as $key0 => $FILES ) (
foreach($FILES as $key => $value ) (
foreach($value as $key2 => $value2 ) (
$uploads [ $key0 ][ $key2 ][ $key ] = $value2 ;
}
}
}
$files = $uploads ;
return $uploads ; // prevent misuse issue
}
?>

3 years ago

This is just a modification of the code which is the top note by "phpuser" here. His/her version requires that the $file_post array passed in to the function was created by a form submitted with the multiple attribute set. With multiple set in the html input tag, $_FILES["fileInputName"]["name"] is an array no matter if only one file is sent or multiple. But when is used without the multiple attribute then $_FILES["fileInputName"]["name"] is not an array, it contains the string with the filename. To use this neat function with or without multiple set and to get back an array which you can "foreach" over in either case, use this modification:

function reArrayFiles(&$file_post)
{
$file_ary = array();
$multiple = is_array($file_post["name"]);

$file_count = $multiple ? count($file_post["name"]) : 1;
$file_keys = array_keys($file_post);

For ($i=0; $i<$file_count; $i++)
{
foreach ($file_keys as $key)
{
$file_ary[$i][$key] = $multiple ? $file_post[$key][$i] : $file_post[$key];
}
}

Return $file_ary;
}

3 years ago

Recursive solution for complex situations (supports any nested arrays including indexed arrays)

function getFixedFilesArray() (
$walker = function ($arr, $fileInfokey, callable $walker) (
$ret = array();
foreach ($arr as $k => $v) (
if (is_array($v)) (
$ret[$k] = $walker($v, $fileInfokey, $walker);
) else (
$ret[$k][$fileInfokey] = $v;
}
}
return $ret;
};

$files = array();
foreach ($_FILES as $name => $values) (
// init for array_merge
if (!isset($files[$name])) (
$files[$name] = array();
}
if (!is_array($values["error"])) (
// normal syntax
$files[$name] = $values;
) else (
// html array feature
foreach ($values ​​as $fileInfoKey => $subArray) (
$files[$name] = array_replace_recursive($files[$name], $walker($subArray, $fileInfoKey, $walker));
}
}
}

Return $files;
}

10 years ago

If you try and upload files with multi-dimensional names like this:


You will get an unexpected format like this:

array(
"submission" => array
"name" => array("screenshot" => "monster_wallpaper.jpg" ),
"type" => array("screenshot" => "image/jpeg" ),
"tmp_name" => array("screenshot" => "/tmp/php48lX2Y" ),
"error" => array("screenshot" => 0 ),
"size" => array("screenshot" => 223262 ),
),
....
?>

You can use the following function to re-format the array recursively in the usual format:

function format_files_array ($files, $name = null, & $new = false, $path = false)(
$names = array("name" => "name" , "type" => "type" , "tmp_name" => "tmp_name" , "error" => "error" , "size" => "size" ) ;

Foreach($files as $key => & $part )
{
$key = (string) $key ;
if(in_array ($key, $names))
$name = $key ;
if(! in_array ($key, $names))
$path = $key ;
if(is_array($part))
$part = format_files_array ($part, $name, $new, $path);
elseif(! is_array($part))
{
$current =& $new ;
foreach($path as $p)
$current =& $current [ $p ];
$current [ $name ] = $part ;
unset($path);
$name = null ;
}
}

Return $new ;
}
?>

In almost every project, the developer is faced with the need to upload files to the server. Photos, pictures, documents, archives and much more can be uploaded to the server via the web interface (via a browser).


Http://localhost/index.php?name=myname&page=10

defines a GET request to the index.php page. In this case, the script is passed the parameters “name” and “page” with the values ​​“myname” and “10”, respectively. As you can see, the request consists of "name=value" pairs, joined by "&". The request is separated from the page address by a question mark "?".

But GET is not suitable for transferring large data. There is a POST method for this. This method transfers data hidden from the user, and the page address remains unchanged. In theory, the POST method allows you to transfer huge blocks of data, but most providers set a hard limit of 5-10 megabytes.

To implement file downloading, it is necessary to provide the user with the appropriate form. The file input tag is used to upload files.

Select file to download:

The user selects the desired file, clicks the “Submit!” button, after which the browser transfers the specified file to the server. Once the file is downloaded, receiver.php is launched, and all data submitted in the form automatically becomes available to it.

The list of downloaded files is stored in the global $_FILES array. This is an associative array, where each element contains a description of one of the files. Let's look at an example:

3145728) ( $filesize = ($filesize != 0)? sprintf("(%.2f MB)" , $filesize / 1024): ""; die("Error: The size of the attached file ". $filesize." is too large (3 MB)."); ) else ( $filename = $_FILES["file"]["name"]; $filepath = $_FILES["file"]["tmp_name"]; $filetype = $_FILES[" file"]["type"]; if($this->filetype == null || $this->filetype == "") $this->filetype = "unknown/unknown"; ) ) ) echo "Loaded successfully file: ". $filename; ?>

All downloaded files are saved by the server in a temporary directory and are automatically deleted after the script completes. If you need to save a file on the server, you need to move it to one of the site directories. There is a special function for this. move_uploaded_file(). It is usually used in conjunction with the function is_uploaded_file(), which allows you to determine whether the file was uploaded through the form. For example:

Information about each downloaded file is represented in the script as elements of the $_FILES array. The element's name is determined by the name attribute of the form tag. In our case, the name attribute is equal to "ufile", which means that data about this file will be stored in the $_FILES["ufile"] element.

Each $_FILES element is also an array containing five elements with fixed names:

The size of downloaded files can vary significantly from provider to provider. Some administrators prohibit file uploads altogether. In this case, the file can still be downloaded, the server will delete it, and inform the script that the file was there, but has already been deleted.

Today, a service for uploading a file to a server (hosting) is found on all social networking sites, message boards, dating sites, etc. Its essence is to enable a visitor to a web resource to publish their files (photos, documents) on the Internet.

There is one significant disadvantage when providing this service. The fact is that by allowing a file to be uploaded to our server, we are, as it were, installing a door behind which constant monitoring is necessary. Since the visitor’s file may contain not only useful information, but also viral code, which can subsequently enable attackers to take over your server. Given this disadvantage, it is necessary to carefully check the files before uploading to the server.

But I won’t intimidate you, but rather present to your attention a ready-made function (PHP script) for checking and uploading files to the server. The function is 100% working. I use it myself on my websites. This function is written for loading image files (photos) in .jpg, .gif, .png format. But if you wish, you can make changes to adapt the PHP script to your needs.

The php script implements two checks:

  1. since the hoster limits the size of the uploaded file (at the time of writing this material, my hosting has a limit of 8 Mb), then checking the maximum size is necessary;
  2. Checking the file extension allows you to weed out unnecessary files before downloading.

I hope there is enough explanation in the function code to understand how to upload a file to the server. But if you have any questions, I will be happy to answer in the comments.

Now let’s talk about how to implement this practically

We place the PHP code of the function in a separate file: function.php and place it on the server in the root directory.

And we will create an html file in which we will place a form for uploading photos: index.html

upload.php - form handler file
name="button" - the name of the button, when clicked, the function of uploading a file to the server is launched

Uploading Multiple Files

Now let's look at the case when you need to upload several files to the server at once.
To do this, we need to make some changes in the function.php upload.php and index.html files.





Perhaps this is all you need to implement a service for uploading a user file to a server (hosting).

Another function that is closely related to loading graphic files (photos) is a function for resizing photos: