PHP 5.4.31 Released

Télécharger plusieurs fichiers simultanément

Le téléchargement de plusieurs fichiers est possible en utilisant des noms différents dans l'attribut name de la balise input.

Il est aussi possible de télécharger plusieurs fichiers simultanément et d'obtenir les informations sous forme de tableau. Pour cela, vous devez utiliser la syntaxe de tableau dans les noms de balises HTML, comme vous l'avez fait avec les sélections multiples et les boîtes à cocher.

Exemple #1 Télécharger plusieurs fichiers simultanément

<form action="file-upload.php" method="post" enctype="multipart/form-data">
  Envoyez plusieurs fichiers : <br />
  <input name="userfile[]" type="file" /><br />
  <input name="userfile[]" type="file" /><br />
  <input type="submit" value="Envoyer les fichiers" />
</form>

Lorsque le formulaire ci-dessus a été envoyé, les tableaux $_FILES['userfile'], $_FILES['userfile']['name'], et $_FILES['userfile']['size'] seront initialisés (tout comme $HTTP_POST_FILES pour les versions PHP antérieures à 4.1.0). Lorsque register_globals est activé, les variables globales concernant les fichiers téléchargés sont aussi initialisées. Chacune d'entre elles contiendra un tableau numériquement indexé, avec les valeurs décrivant les fichiers téléchargés.

Par exemple, supposons que les fichiers /home/test/review.html et /home/test/xwp.out ont été téléchargés. Dans ce cas, $_FILES['userfile']['name'][0] contient review.html et $_FILES['userfile']['name'][1] contient xwp.out. Similairement, $_FILES['userfile']['size'][0] va contenir la taille du fichier review.html, etc.

$_FILES['userfile']['name'][0], $_FILES['userfile']['tmp_name'][0], $_FILES['userfile']['size'][0] et $_FILES['userfile']['type'][0] sont aussi créées.

Avertissement

Depuis PHP 5.2.12, le paramètre max_file_uploads limite le nombre de fichiers qui peuvent être envoyés en une requête. Vous devrez vérifier que votre formulaire ne tente pas d'envoyer plus de fichiers dans la requête que ne le tolère cette limite.

add a note add a note

User Contributed Notes 10 notes

up
65
phpuser at gmail dot com
9 years ago
When uploading multiple files, the $_FILES variable is created in the form:

Array
(
    [name] => Array
        (
            [0] => foo.txt
            [1] => bar.txt
        )

    [type] => Array
        (
            [0] => text/plain
            [1] => text/plain
        )

    [tmp_name] => Array
        (
            [0] => /tmp/phpYzdqkD
            [1] => /tmp/phpeEwEWG
        )

    [error] => Array
        (
            [0] => 0
            [1] => 0
        )

    [size] => Array
        (
            [0] => 123
            [1] => 456
        )
)

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

Array
(
    [0] => Array
        (
            [name] => foo.txt
            [type] => text/plain
            [tmp_name] => /tmp/phpYzdqkD
            [error] => 0
            [size] => 123
        )

    [1] => Array
        (
            [name] => bar.txt
            [type] => text/plain
            [tmp_name] => /tmp/phpeEwEWG
            [error] => 0
            [size] => 456
        )
)

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

<?php

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:

<?php

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'];
    }
}

?>
up
9
Corey Ballou
4 years ago
Here is a function to fix the indices 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:

<?php
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:

<?php
/**
* 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]);
        }
    }
}
?>
up
10
wizzard351 at yahoo dot com
6 months ago
This is also needed for <input type=file multiple> elements.

So, if you have an input element like this:
<input type="file" multiple="multiple" name="foobar" />
This should be written as
<input type="file" multiple="multiple" name="foobar[]" />
else you'll only be able to get one of the files.
up
9
timspeelman at live dot nl
2 years ago
The cleanest way to rearrange the $_FILES

<?php
function rearrange( $arr ){
    foreach(
$arr as $key => $all ){
        foreach(
$all as $i => $val ){
           
$new[$i][$key] = $val;   
        }   
    }
    return
$new;
}
?>
up
1
javad dot geek at gmail dot com
5 months ago
$countarray = count($_FILES['uploadfile']['name']);
                $newarray = array();
                for($i=0;$i<$countarray;$i++){
                    $newarray[$i]['name']=$_FILES['uploadfile']['name'][$i];
                    $newarray[$i]['type']=$_FILES['uploadfile']['type'][$i];
                    $newarray[$i]['tmp_name']=$_FILES['uploadfile']['tmp_name'][$i];
                    $newarray[$i]['error']=$_FILES['uploadfile']['error'][$i];
                    $newarray[$i]['size']=$_FILES['uploadfile']['size'][$i];
                }
up
0
jess at semlabs dot co dot uk
5 years ago
If you try and upload files with multi-dimensional names like this:

<input type="file" name="submission[screenshot]" />
<input type="file" name="other[dem][][img][]" />

You will get an unexpected format like this:

<?php
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:

<?php
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;
}
?>
up
-1
contato at dgmike dot com dot br
3 years ago
I prefer something like this!

<?php
public function arrayImages ( &$file_post )
{
    if( empty(
$file_post ) ) {
        return
$file_post;
    }
    if(
'array'!==gettype($file_post['name']) ) {
        return
$file_post;
    }
   
$keys = array_keys($file_post['name']);
   
$file_array = array();
    foreach (
$keys as $key) {
       foreach (
$file_post as $res=>$item) {
          
$file_array[$key][$res] = $item[$key];
       }
   }
   return
$file_array;
}
?>
up
-1
hotmail.com[at]notdefix
6 years ago
With multiple file uploads

post_max_size: the total amount of data posted by the client (all files, and all other form field)

upload_max_filesize: the maximum size of 1 single file. (just like <input type="hidden" name="MAX_FILE_SIZE" value="..."/>)

so, with the directives:
post_max_size 25M
upload_max_filesize 2M

you can send 12 files of up to 2 MB and use up to 1 MB for your additional form-values.

As long as you read only a single copy of 1 file into memory, the memory_limit directive can be held reasonable small as well.
up
-5
ohcnim at hotmail dot com
11 months ago
by simply naming differently each file input you'll get easily accesible arrays from $_FILES, in the form $_FILES['input_name']['file_attribute'].  For example:

$_FILES['input_name1']['name']...['input_name1']['size']
$_FILES['input_name2']['name']...['input_name2']['size']
$_FILES['input_nameX']['name']...['input_nameX']['size']
up
-12
christiaan at baartse dot nl
4 years ago
After trying dozens of ways that are supposed to fix the wonkyness of the $_FILES array I didn't find any that could work with a input name like: userfile[christiaan][][][is][gaaf][]

So I came up with this class
<?php
/**
* A class that takes the pain out of the $_FILES array
* @author Christiaan Baartse <christiaan@baartse.nl>
*/
class UploadedFiles extends ArrayObject
{
    public function
current() {
        return
$this->_normalize(parent::current());
    }

    public function
offsetGet($offset) {
        return
$this->_normalize(parent::offsetGet($offset));
    }

    protected function
_normalize($entry) {
        if(isset(
$entry['name']) && is_array($entry['name'])) {
           
$files = array();
            foreach(
$entry['name'] as $k => $name) {
               
$files[$k] = array(
                   
'name' => $name,
                   
'tmp_name' => $entry['tmp_name'][$k],
                   
'size' => $entry['size'][$k],
                   
'type' => $entry['type'][$k],
                   
'error' => $entry['error'][$k]
                );
            }
            return new
self($files);
        }
        return
$entry;
    }
}
?>

This allows you to access a file uploaded using the following inputtype
<input type="file" name="userfile[christiaan][][][is][gaaf][]" />
like
<?php
$files
= new UploadedFiles($_FILES);
var_dump($files['userfile']['christiaan'][0][0]['is']['gaaf'][0]);
// or
foreach($files['userfile']['christiaan'][0][0]['is']['gaaf'] as $file) {
   
var_dump($file);
}
?>
To Top