PHP
downloads | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Chargement par méthode PUT> <Erreurs classiques
Last updated: Fri, 10 Oct 2008

view this page in

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 de PHP antérieures à la 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.



Chargement par méthode PUT> <Erreurs classiques
Last updated: Fri, 10 Oct 2008
 
add a note add a note User Contributed Notes
Télécharger plusieurs fichiers simultanément
tom at nono dot be
18-Mar-2008 04:04
Handling multiple uploads can be a lot more user friendly with a little help of javascript and form posting to iFrame...
To make it all a little bit more edible, you can use AJAX and divs to provide loader gifs etc...

Work with separate forms; note the target of each form = csr. It is the ID of an iFrame somewhere on the page. I call it CSR as short for Client-Server-Request.

Also note the hidden input formId that we will use in the php upload handler.

disable submitting the form using onsubmit="return false"...

Finally a button outside the form structure starting a javascript function onclick="upload(document.form_0, document.loader_0)"

<form onsubmit="return false" id="file_0" name="file_0" action="upload.php" target="csr" enctype="multipart/form-data" method="post" style="margin:px; padding:0px">
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td>File 1:</td>
            <td>
                <input type="hidden" id="formId" name="formId" value="0" />
                <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="1000000" />
                <input type="file" id="userFile" name="userFile" class="invulveld100pct" />
            </td>
            <td>
                <div id="loader_0"></div>
            </td>
        </tr>
    </table>
</form>
<form onsubmit="return false" id="file_1" name="file_1" action="upload.php" target="csr" enctype="multipart/form-data" method="post" style="margin:px; padding:0px">
    <table width="100%" border="0" cellspacing="0" cellpadding="0">
        <tr>
            <td>File 2:</td>
            <td>
                <input type="hidden" id="formId" name="formId" value="1" />
                <input type="hidden" id="MAX_FILE_SIZE" name="MAX_FILE_SIZE" value="1000000" />
                <input type="file" id="userFile" name="userFile" class="invulveld100pct" />
            </td>
            <td>
                <div id="loader_0"></div>
            </td>
        </tr>
    </table>
</form>
<input type="button" onclick="upload(document.form_0, document.loader_0)" />
<iframe id="csr" name="csr" height="1" width="1" style="border:0px none"></iframe>

<!--//The javascript://-->

<script type="javascript">
function upload(form, loader){
    //only do this if the form exists
    if(form){
        //display a loadbar
        loader.innerHTML = 'loading.gif';
        form.submit();
    }
}
</script>

The php upload handler upload.php
Remember, your page will not refresh because the post is sent to your CSR iFrame.

<?php
//there are enough examples around to handle the upload...
//the only important difference is the error reporting and the starting of the next form upload...
//presume $uploadOk is a boolean that is true if the upload succeeds; false if it fails...
//note the use of "parent" in the outputted javascript... the script is outputted into the CSR iFrame... therefor it needs parent to acces dom objects and javascript of the main page.

$currentFormId = $_POST['formId'];
$nextFormId = $_POST['formId'] + 1;

echo
"<script type=\"javascript\">";

//change the content of your loader div to a desired image
if($uploadOk){
    echo
"parent.loader_{$currentFormId}.innerHTML = 'uploadOk.gif';";
} else {
    echo
"parent.loader_{$currentFormId}.innerHTML = 'uploadNotOk.gif';";
}

//submit the next form... the javascript function will only perform it if the form exists.
echo "parent.upload(document.form_{$nextFormId}, document.loader_{$nextFormId});";

echo
"</script>";

?>

This is just a quick draft of how to handle multiple files this way and I'm sure you would need to optimize the workflow to fit your needs, but the benifit of working this way is although your user still chooses multiple files, they are in fact posted one by one... This means your MAX_FILE_SIZE is determined for each file separately as opposed to the combined size of all files in one post.

I hope this is a contribution...
hotmail.com[at]notdefix
27-Sep-2007 04:47
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.
captlid at yahoo dot com
23-Feb-2007 03:08
I noticed that the manual does not have a basic processing script for testing purposes to process multiple file uploads. It took me about an hour to figure this out so I figured it should help some newbie.

Also on windows, the OS does not care if you use backslashes and front slashes while writing up a directory path. So for compatibility with *nix just keep it as a foward slash.

(Tested with php5, php4, apache 1.3x and 2x, on winxp pro, win2k pro and win98se and freebsd.)

The script is kept simple for illustration purposes. Dont use it in a production environment.

The form

<form method="post" action="" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="500000">
<?
for($i = 1; $i <= $_POST[totalfiles]; $i++) { echo $i.'. <input type="file" name="photos[]"><br>'."\n"; }
?>
<input type="submit" name="sendfiles" value="Send Files"></form>

The processing script, for simplicities sake in the same file.

if ($_POST[sendfiles]) {
print_r($_POST); echo '<pre>'; print_r($_FILES); echo '</pre>';

$uploaddir = getcwd().'/photos/; //a directory inside
foreach ($_FILES[photos][name] as $key => $value) {
$uploadfile = $uploaddir . basename($_FILES[photos][name][$key]);
//echo $uploadfile;
if (move_uploaded_file($_FILES['photos']['tmp_name'][$key], $uploadfile)) { echo $value . ' uploaded<br>'; }
}
}
Bob Doe
08-Aug-2005 11:17
Here is a the simple test form I needed, pieced togther from 2 or 3 posts in the documentation elsewhere.

<html>
<head>
<title>HTML Form for uploading image to server</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<p>Pictures:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Send" />
</p>
</form>
<?php
//places files into same dir as form resides
foreach ($_FILES["pictures"]["error"] as $key => $error) {
   if (
$error == UPLOAD_ERR_OK) {
       echo
"$error_codes[$error]";
      
move_uploaded_file(
        
$_FILES["pictures"]["tmp_name"][$key],
        
$_FILES["pictures"]["name"][$key]
       ) or die(
"Problems with upload");
   }
}
?>
</body>
</html>
29-Jul-2005 04:50
re: phpuser's comment

I found that if instead of the form structure at the top of the page use one like this:

<form action="file-upload.php" method="post" enctype="multipart/form-data">
  Send these files:<br />
  <input name="userfile1" type="file" /><br />
  <input name="userfile2" type="file" /><br />
  <input type="submit" value="Send files" />
</form>

Notice the names are unique and not an array element.  Now the array is structured more like phpuser would like. I did this and used...

foreach ($_FILES as $file) { ... }

without issue.
sgoodman_at_nojunk_immunetolerance.org
17-Jun-2005 04:03
Re: phpuser_at_gmail's comment, a simpler way to have create that data structure is to name your HTML file inputs different names. If you want to upload multiple files, use:
<input type=file name=file1>
<input type=file name=file2>
<input type=file name=file3>
etc...
Each field name will be a key in the $_FILES array.
bishop
02-Jun-2005 08:27
Elaboration on phpuser at gmail dot com reArrayFiles() function (which assumed sequential, integer keys and uni-dimensional), this function will work regardless of key and key depth:

<?php
// information grouper
function groupFileInfoByVariable(&$top, $info, $attr) {
    if (
is_array($info)) {
        foreach (
$info as $var => $val) {
            if (
is_array($val)) {
               
groupFileInfoByVariable($top[$var], $val, $attr);
            } else {
               
$top[$var][$attr] = $val;
            }
        }
    } else {
       
$top[$attr] = $info;
    }

    return
true;
}

// usage
$newOrdering = array ();
foreach (
$_FILES as $var => $info) {
    foreach (
array_keys($info) as $attr) {
       
groupFileInfoByVariable($newOrdering, $info[$attr], $attr);
    }
}

// $newOrdering holds the updated order
?>
phpuser at gmail dot com
26-May-2005 05:09
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'];
    }
}

?>

Chargement par méthode PUT> <Erreurs classiques
Last updated: Fri, 10 Oct 2008
 
 
show source | credits | stats | sitemap | contact | advertising | mirror sites