Many times we need to perform multiple file uploads using the same web form but how do we do that? Better, how do we do it without even knowing how many files our user wants to upload. This is quite easy in PHP and it only needs a little more attention. Let's consider our form with a single input for a file:
<input type="file" name"picture" />
When submitted, if we print the $_FILES, variable we get something like this:
array ( 'name' => '', 'tmp_name' => '', 'error' => '', 'size' => '' )
This forces us to look for the name of the file input and try to access it from the $_FILES variable and so on for each file input we need. But this keeps us static and we can't really let our user upload as much as he wants so we need to modify our file input a little bit:
<input type="file" name"picture[]" />
The above type (notice the [] brackets placed at the end of the file name: picture[]) allows us to add as many file inputs with the same name. From now on, it's just a matter of adding a little javascript and a link under our file which, when clicked, will create new file inputs in order for our user to have control on the quantity.
function add_file_input(){
$('#container-div').append('<input type="file" name="picture[]" />');
}
The above jquery snippet appends file inputs to a container with id set to 'container-div' so all we need to do right now is to wrap our file input in a div element with the required id.
<script type="text/javascript">
function add_file_input(){
$('#container-div').append('<input type="file" name="picture[]" />');
}
</script>
<div id="container-div">
<input type="file" name"picture[]" />
<a href="javascript:void(0);" onclick="add_file_input();">Add field</a>
</div>
That's just about it on the client side. We now need to figure out a way to access all the files submitted by the user in a smart foreach loop to make sure we address them all.
foreach ( $_FILES [ 'picture' ] [ "error" ] as $key => $error ) {
if ( $error == UPLOAD_ERR_OK ) {
$tmp_name = $_FILES [ "picture" ] [ "tmp_name" ] [ $key ];
$name = $_FILES [ "pictures" ] [ "name" ] [ $key ];
@move_uploaded_file ( $tmp_name, "$uploads_dir/$name" );
}
}
That's it! In just 7 lines we managed to write the code which is capable of uploading an unlimited number of files (the only limitation is on the server, see max upload size, max execution time etc.) without too much hassle. Of course, you need to define the $uploads_dir/ variable and place the path to your uploads directory there. You also need to make sure it's writable by the server. Here's our final script:
<?php
$uploaded_files = 0;
$skipped_files = 0;
$uploads_dir = realpath ( dirname ( __FILE__ ) ) . DIRECTORY_SEPARATOR . "uploads";
if ( ! empty ( $_FILES ) ) {
foreach ( $_FILES [ 'picture' ] [ "error" ] as $key => $error ) {
if ( $error == UPLOAD_ERR_OK ) {
$tmp_name = $_FILES [ "picture" ] [ "tmp_name" ] [ $key ];
$name = $_FILES [ "picture" ] [ "name" ] [ $key ];
if ( move_uploaded_file ( $tmp_name, "$uploads_dir/$name" ) ) {
$uploaded = TRUE;
$uploaded_files++;
}
else {
$skipped_files++;
}
}
else {
$skipped_files++;
}
}
}
if ( $uploaded_files ) {
echo "Upload finished! Uploaded files $uploaded_files, skipped $skipped_files";
}
else {
?>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function add_file_input(){
$('#container-div').append('<input type="file" name="picture[]" /><br />');
}
</script>
<form action="" enctype="multipart/form-data" method="post">
<div id="container-div">
<input type="file" name="picture[]" /><br />
</div>
<input type="submit" value="Upload" />
<a href="javascript:void(0);" onclick="add_file_input();">Add field</a>
</form>
<?php } ?>
Don't forget to download our example:multiple_uploads.zip