Comment puis-je sélectionner et télécharger plusieurs fichiers avec HTML et PHP, en utilisant HTTP POST?

155

J'ai de l'expérience avec les téléchargements de fichiers uniques en utilisant <input type="file">. Cependant, j'ai du mal à en télécharger plus d'un à la fois.

Par exemple, j'aimerais pouvoir sélectionner une série d'images, puis les télécharger sur le serveur, toutes en même temps.

Ce serait bien d'utiliser un seul contrôle d'entrée de fichier, si possible.

Est ce que quelqu'un sait comment accomplir cela? Merci!

stalepretzel
la source
2
Voulez-vous dire sélectionner plusieurs fichiers dans la boîte de dialogue de sélection de fichiers ou utiliser plusieurs entrées de fichiers?
MitMaro
Salut, Il vous est possible de télécharger un fichier archive (zip, rar, tar, ...)?
sourcerebels

Réponses:

196

Ceci est possible en HTML5 . Exemple (PHP 5.4):

<!doctype html>
<html>
    <head>
        <title>Test</title>
    </head>
    <body>
        <form method="post" enctype="multipart/form-data">
            <input type="file" name="my_file[]" multiple>
            <input type="submit" value="Upload">
        </form>
        <?php
            if (isset($_FILES['my_file'])) {
                $myFile = $_FILES['my_file'];
                $fileCount = count($myFile["name"]);

                for ($i = 0; $i < $fileCount; $i++) {
                    ?>
                        <p>File #<?= $i+1 ?>:</p>
                        <p>
                            Name: <?= $myFile["name"][$i] ?><br>
                            Temporary file: <?= $myFile["tmp_name"][$i] ?><br>
                            Type: <?= $myFile["type"][$i] ?><br>
                            Size: <?= $myFile["size"][$i] ?><br>
                            Error: <?= $myFile["error"][$i] ?><br>
                        </p>
                    <?php
                }
            }
        ?>
    </body>
</html>

Voici à quoi cela ressemble dans Chrome après avoir sélectionné 2 éléments dans la boîte de dialogue de fichier:

chrome sélection de plusieurs fichiers

Et voici à quoi cela ressemble après avoir cliqué sur le bouton "Télécharger".

soumettre plusieurs fichiers à PHP

Ceci est juste une esquisse d'une réponse pleinement fonctionnelle. Voir Manuel PHP: Gestion des téléchargements de fichiers pour plus d'informations sur la gestion correcte et sécurisée des téléchargements de fichiers en PHP.

Mark E. Haase
la source
8
passe-t-il la validation W3C, ou devrait-il l'être multiple="multiple"?
vol7ron
10
Je crois que c'est valide: thinkresults.com/html5-boolean-attributes . Il passe le validateur w3c si vous ajoutez <! Doctype html>.
Mark E. Haase
2
ouais, il valide probablement HTML, mais échoue XHTML. Même si j'aime toujours utiliser XHTML, je pense que les gens conseillent de rester à l'écart ces jours-ci.
vol7ron
11
Cela ne fonctionnait pas sans ajouter le nom de la propriété (par exemple name="file[]"). J'ai essayé de modifier la réponse , mais elle a été rejetée.
Michel Ayres
1
Merci @MichelAyres, j'ai mis à jour ma réponse. Lorsque j'ai initialement écrit ceci, je n'ai abordé que la partie HTML du problème car il y avait d'autres réponses qui expliquaient la partie PHP. Au fil du temps, cela est devenu une réponse populaire, donc je l'ai maintenant étendu pour couvrir à la fois HTML et PHP.
Mark E. Haase
94

Il y a quelques choses que vous devez faire pour créer un téléchargement de plusieurs fichiers, c'est assez basique en fait. Vous n'avez pas besoin d'utiliser Java, Ajax, Flash. Créez simplement un formulaire de téléchargement de fichiers normal en commençant par:

<form enctype="multipart/form-data" action="post_upload.php" method="POST">

Puis la clé du succès;

<input type="file" name="file[]" multiple />

N'oubliez PAS ces parenthèses! Dans le post_upload.php, essayez ce qui suit:

<?php print_r($_FILES['file']['tmp_name']); ?>

Notez que vous obtenez un tableau avec des données tmp_name, ce qui signifie que vous pouvez accéder à chaque fichier avec une troisième paire de crochets avec l'exemple de fichier 'number':

$_FILES['file']['tmp_name'][0]

Vous pouvez utiliser php count () pour compter le nombre de fichiers sélectionnés. Goodluck widdit!

Époxys
la source
5
Merci pour le conseil! cela m'a fait gagner beaucoup de temps +1
BPm
Cela fonctionne très bien ... mais j'ai du mal à télécharger de cette façon dans Internet Explorer (v8). Je pense que IE ne prend pas en charge le téléchargement de cette façon.
Tariq M Nasim
4
Ou vous pouvez parcourir les fichiers avec une foreachdéclaration, sans avoir à connaître le nombre de fichiers téléchargés ...
ygesher
Notez que si vous utilisez une clé dans votre nom dans votre html, par exemple name = "file [3]", alors vous devez accéder à la valeur via $ _FILES ['file'] ['tmp_name'] [3], au cas où ce n'est pas évident.
MyStream
8

Solution complète dans Firefox 5:

<html>
<head>
</head>
<body>
 <form name="uploader" id="uploader" action="multifile.php" method="POST" enctype="multipart/form-data" >
  <input id="infile" name="infile[]" type="file" onBlur="submit();" multiple="true" ></input> 
 </form>

<?php
echo "No. files uploaded : ".count($_FILES['infile']['name'])."<br>"; 


$uploadDir = "images/";
for ($i = 0; $i < count($_FILES['infile']['name']); $i++) {

 echo "File names : ".$_FILES['infile']['name'][$i]."<br>";
 $ext = substr(strrchr($_FILES['infile']['name'][$i], "."), 1); 

 // generate a random new file name to avoid name conflict
 $fPath = md5(rand() * time()) . ".$ext";

 echo "File paths : ".$_FILES['infile']['tmp_name'][$i]."<br>";
 $result = move_uploaded_file($_FILES['infile']['tmp_name'][$i], $uploadDir . $fPath);

 if (strlen($ext) > 0){
  echo "Uploaded ". $fPath ." succefully. <br>";
 }
}
echo "Upload complete.<br>";
?>

</body>
</html>
Thaps
la source
Le code a été coupé. Voici ce qui vient juste au-dessus: <html> <head> </head> <body> <form name="uploader" id="uploader" action="multifile.php" method="POST" enctype="multipart/form-data" > <input id="infile" name="infile[]" type="file" onBlur="submit();" multiple="true" ></input> </form>
Thaps
3
Cela ne fonctionnait pas dans IE8, mais utilisez simplement un vrai navigateur.
Thaps
5

Si vous souhaitez sélectionner plusieurs fichiers dans la boîte de dialogue du sélecteur de fichiers qui s'affiche lorsque vous sélectionnez Parcourir, vous n'avez généralement pas de chance. Vous devrez utiliser une applet Java ou quelque chose de similaire (je pense qu'il y en a un qui utilise un petit fichier flash, je le mettrai à jour si je le trouve). Actuellement, une seule entrée de fichier ne permet la sélection que d'un seul fichier.

Si vous parlez d'utiliser plusieurs entrées de fichier, il ne devrait pas y avoir beaucoup de différence par rapport à l'utilisation d'une seule. Postez du code et j'essaierai de vous aider davantage.


Mise à jour: il existe une méthode pour utiliser un seul bouton «parcourir» qui utilise flash. Je ne l'ai jamais utilisé personnellement mais j'en ai lu pas mal. Je pense que c'est votre meilleur coup.

http://swfupload.org/

MitMaro
la source
1
J'ai ajouté le lien vers le téléchargeur multiple basé sur flash.
MitMaro le
J'ai utilisé swfupload fwiw - c'est un peu pénible à l'occasion, mais ce n'est pas vraiment difficile de travailler.
Meep3D
@Barsoom a raison. Les choses se sont beaucoup améliorées avec les téléchargements de fichiers multiples au cours des deux dernières années. : D
MitMaro
4

dans le premier, vous devez créer une forme comme celle-ci:

<form method="post" enctype="multipart/form-data" >
   <input type="file" name="file[]" multiple id="file"/>
   <input type="submit" name="ok"  />
</form> 

c'est vrai . ajoutez maintenant ce code sous votre code de formulaire ou sur la page de votre choix

<?php
if(isset($_POST['ok']))
   foreach ($_FILES['file']['name'] as $filename) {
    echo $filename.'<br/>';
}
?>

c'est facile ... finir

pooya laryan
la source
1

Si vous utilisez plusieurs champs de saisie, vous pouvez définir name = "file []" (ou tout autre nom). Cela les mettra dans un tableau lorsque vous les téléchargez ( $_FILES['file'] = array ({file_array},{file_array]..))

Torandi
la source
1
<form action="" method="POST" enctype="multipart/form-data">
  Select image to upload:
  <input type="file"   name="file[]" multiple/>
  <input type="submit" name="submit" value="Upload Image" />
</form>

Utilisation de la boucle FOR

<?php    
  $file_dir  = "uploads";    
  if (isset($_POST["submit"])) {

    for ($x = 0; $x < count($_FILES['file']['name']); $x++) {               

      $file_name   = $_FILES['file']['name'][$x];
      $file_tmp    = $_FILES['file']['tmp_name'][$x];

      /* location file save */
      $file_target = $file_dir . DIRECTORY_SEPARATOR . $file_name; /* DIRECTORY_SEPARATOR = / or \ */

      if (move_uploaded_file($file_tmp, $file_target)) {                        
        echo "{$file_name} has been uploaded. <br />";                      
      } else {                      
        echo "Sorry, there was an error uploading {$file_name}.";                               
      }                 

    }               
  }    
?>

Utilisation de la boucle FOREACH

<?php
  $file_dir  = "uploads";    
  if (isset($_POST["submit"])) {

    foreach ($_FILES['file']['name'] as $key => $value) {                   

      $file_name   = $_FILES['file']['name'][$key];
      $file_tmp    = $_FILES['file']['tmp_name'][$key];

      /* location file save */
      $file_target = $file_dir . DIRECTORY_SEPARATOR . $file_name; /* DIRECTORY_SEPARATOR = / or \ */

      if (move_uploaded_file($file_tmp, $file_target)) {                        
        echo "{$file_name} has been uploaded. <br />";                      
      } else {                      
        echo "Sorry, there was an error uploading {$file_name}.";                               
      }                 

    }               
  }
?>
antelove
la source
0

J'ai créé une fonction php qui est utilisée pour télécharger plusieurs images, cette fonction peut télécharger plusieurs images dans un dossier spécifique ainsi qu'elle peut enregistrer les enregistrements dans la base de données dans le code suivant $ arrayimage est le tableau d'images qui est envoyé via la note de formulaire qu'il n'autorisera pas le téléchargement à utiliser plusieurs mais vous devez créer un champ de saisie différent avec le même nom, car vous pouvez définir le champ d'ajout dynamique du fichier unput en cliquant sur le bouton.

$ dir est le répertoire dans lequel vous souhaitez enregistrer l'image $ fields est le nom du champ que vous souhaitez stocker dans la base de données

Le champ de base de données doit être dans un exemple de format de tableau si vous avez une image de base de données et un nom de champs comme id, nom, adresse, vous devez publier des données telles que

$fields=array("id"=$_POST['idfieldname'], "name"=$_POST['namefield'],"address"=$_POST['addressfield']);

puis passez ce champ dans la fonction $ fields

$ table est le nom de la table dans laquelle vous souhaitez stocker les données.

function multipleImageUpload($arrayimage,$dir,$fields,$table)
{
    //extracting extension of uploaded file
    $allowedExts = array("gif", "jpeg", "jpg", "png");
    $temp = explode(".", $arrayimage["name"]);
    $extension = end($temp);

    //validating image
    if ((($arrayimage["type"] == "image/gif")
    || ($arrayimage["type"] == "image/jpeg")
    || ($arrayimage["type"] == "image/jpg")
    || ($arrayimage["type"] == "image/pjpeg")
    || ($arrayimage["type"] == "image/x-png")
    || ($arrayimage["type"] == "image/png"))

    //check image size

    && ($arrayimage["size"] < 20000000)

    //check iamge extension in above created extension array
    && in_array($extension, $allowedExts)) 
    {
        if ($arrayimage["error"] > 0) 
        {
            echo "Error: " . $arrayimage["error"] . "<br>";
        } 
        else 
        {
            echo "Upload: " . $arrayimage["name"] . "<br>";
            echo "Type: " . $arrayimage["type"] . "<br>";
            echo "Size: " . ($arrayimage["size"] / 1024) . " kB<br>";
            echo "Stored in: ".$arrayimage['tmp_name']."<br>";

            //check if file is exist in folder of not
            if (file_exists($dir."/".$arrayimage["name"])) 
            {
                echo $arrayimage['name'] . " already exists. ";
            } 
            else 
            {
                //extracting database fields and value
                foreach($fields as $key=>$val)
                {
                    $f[]=$key;
                    $v[]=$val;
                    $fi=implode(",",$f);
                    $value=implode("','",$v);
                }
                //dynamic sql for inserting data into any table
                $sql="INSERT INTO " . $table ."(".$fi.") VALUES ('".$value."')";
                //echo $sql;
                $imginsquery=mysql_query($sql);
                move_uploaded_file($arrayimage["tmp_name"],$dir."/".$arrayimage['name']);
                echo "<br> Stored in: " .$dir ."/ Folder <br>";

            }
        }
    } 
    //if file not match with extension
    else 
    {
        echo "Invalid file";
    }
}
//function imageUpload ends here
}

// La classe imageFunctions se termine ici

vous pouvez essayer ce code pour insérer plusieurs images avec son extension cette fonction est créée pour vérifier les fichiers image vous pouvez remplacer la liste des extensions pour les fichiers concernés dans le code

Prateik Darji
la source
Salut à tous, j'utilise l'entrée de fichier pour joindre des documents à un e-mail généré automatiquement. Je suis capable de joindre plusieurs documents à la fois, cependant, je voudrais joindre plusieurs documents à partir de différents répertoires. Actuellement, si je fais cela, mon document actuellement sélectionné est remplacé par le nouveau document que je sélectionne. S'il vous plaît, comment dois-je procéder. Merci
Kunbi
-1

réponse partielle: poire HTTP_UPLOAD peut être utile http://pear.php.net/manual/en/package.http.http-upload.examples.php

il y a un exemple complet pour plusieurs fichiers

Damko
la source
1
Vous pouvez utiliser le package PEAR mais cette tâche est assez simple et à moins que vous n'ayez besoin des fonctionnalités supplémentaires fournies par le package (messages d'erreur internationalisés, validation, etc.), je recommanderais d'utiliser les fonctions PHP natives. Mais ce n'est que mon avis. :)
MitMaro
Je suis d'accord avec vous, c'est pourquoi j'ai écrit "réponse partielle". Mais je fais aussi de mon mieux pour réutiliser le code et je travaille souvent autant que je peux avec pear (les codeurs de poire sont bien meilleurs que moi :-D)
damko