¿Cómo puedo seleccionar y cargar múltiples archivos con HTML y PHP, usando HTTP POST?

155

Tengo experiencia haciendo esto con cargas de archivos individuales usando <input type="file">. Sin embargo, tengo problemas para cargar más de uno a la vez.

Por ejemplo, me gustaría poder seleccionar una serie de imágenes y luego subirlas al servidor, todo a la vez.

Sería genial usar un solo control de entrada de archivo, si es posible.

¿Alguien sabe cómo lograr esto? ¡Gracias!

Stalepretzel
fuente
2
¿Quiere decir seleccionar más de un archivo en el cuadro de diálogo del selector de archivos o usar múltiples entradas de archivo?
MitMaro el
Hola, ¿Es posible que subas un archivo (zip, rar, tar, ...)?
sourcerebels

Respuestas:

196

Esto es posible en HTML5 . Ejemplo (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>

Así es como se ve en Chrome después de seleccionar 2 elementos en el cuadro de diálogo de archivo:

selección de archivos múltiples de Chrome

Y así es como se ve después de hacer clic en el botón "Cargar".

enviando múltiples archivos a PHP

Esto es solo un boceto de una respuesta totalmente funcional. Consulte el Manual PHP: Manejo de cargas de archivos para obtener más información sobre el manejo adecuado y seguro de las cargas de archivos en PHP.

Mark E. Haase
fuente
8
¿pasa la validación w3c, o debería ser multiple="multiple"?
vol7ron
10
Creo que es válido: thoughtresults.com/html5-boolean-attributes . Pasa el validador w3c si agrega <! Doctype html>.
Mark E. Haase
2
Sí, probablemente valida HTML, pero falla XHTML. A pesar de que todavía me gusta usar XHTML, creo que la gente aconseja mantenerse alejado de él en estos días.
vol7ron
11
No funcionó sin agregar el nombre de la propiedad (por ejemplo name="file[]"). Intenté editar la respuesta , pero fue rechazada.
Michel Ayres
1
Gracias @MichelAyres, he actualizado mi respuesta. Cuando originalmente escribí esto, solo abordé la parte HTML del problema b / c, había otras respuestas que explicaban la parte PHP. Con el tiempo, esta se convirtió en una respuesta popular, por lo que ahora me he expandido para cubrir tanto HTML como PHP.
Mark E. Haase
94

Hay algunas cosas que debes hacer para crear una carga de archivos múltiples, en realidad es bastante básico. No necesita usar Java, Ajax, Flash. Simplemente cree un formulario de carga de archivos normal comenzando con:

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

Entonces la clave del éxito;

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

¡NO olvides esos corchetes! En post_upload.php intente lo siguiente:

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

Observe que obtiene una matriz con datos de tmp_name, lo que significa que puede acceder a cada archivo con un tercer par de paréntesis con el ejemplo de 'número' del archivo:

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

Puede usar php count () para contar la cantidad de archivos que se seleccionó. ¡Buena suerte!

Epoxis
fuente
55
¡Gracias por el consejo! me ahorró mucho tiempo +1
BPm
Funciona muy bien ... pero tengo problemas para cargar de esta manera en Internet Explorer (v8). Creo que IE no admite la carga de esta manera.
Tariq M Nasim
44
O puede recorrer los archivos con un foreachcomunicado, sin tener que conocer el número de archivos cargado ...
ygesher
Tenga en cuenta que si usa una clave en su nombre en su html, por ejemplo, name = "file [3]", entonces necesita acceder al valor a través de $ _FILES ['file'] ['tmp_name'] [3], en caso Eso no es obvio.
MyStream
8

Solución completa en 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
fuente
El código recortado. Esto es lo que se produce justo por encima de ella: <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
Sin embargo, no funcionó en IE8, pero solo usé un navegador real.
Thaps
5

Si desea seleccionar varios archivos desde el cuadro de diálogo del selector de archivos que se muestra cuando selecciona examinar, no tendrá suerte. Necesitará usar un applet de Java o algo similar (creo que hay uno que usa un pequeño archivo flash, lo actualizaré si lo encuentro). Actualmente, una entrada de un solo archivo solo permite la selección de un solo archivo.

Si está hablando de usar múltiples entradas de archivo, entonces no debería haber mucha diferencia de usar una. Publica un código e intentaré ayudarte más.


Actualización: hay un método para usar un solo botón 'navegar' que usa flash. Nunca lo he usado personalmente, pero he leído bastante al respecto. Creo que es tu mejor oportunidad.

http://swfupload.org/

MitMaro
fuente
1
Agregué el enlace al cargador múltiple basado en flash.
MitMaro
He usado swfupload fwiw, es un poco doloroso en ocasiones, pero en realidad no es tan difícil trabajar.
Meep3D el
@Barsoom es correcto. Las cosas han mejorado mucho en la carga de múltiples archivos en los últimos dos años. : D
MitMaro
4

en el primero debes hacer una forma como esta:

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

eso es correcto . ahora agregue este código debajo de su código de formulario o en la página que desee

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

es fácil ... terminar

pooya laryan
fuente
1

Si utiliza múltiples campos de entrada, puede establecer name = "file []" (o cualquier otro nombre). Eso los colocará en una matriz cuando los cargue ( $_FILES['file'] = array ({file_array},{file_array]..))

Torandi
fuente
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>

Usando FOR Loop

<?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}.";                               
      }                 

    }               
  }    
?>

Usando FOREACH Loop

<?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}.";                               
      }                 

    }               
  }
?>
antílope
fuente
0

he creado una función php que se usa para cargar múltiples imágenes, esta función puede cargar múltiples imágenes en una carpeta específica y también puede guardar los registros en la base de datos en el siguiente código $ arrayimage es el conjunto de imágenes que se envía a través de la nota del formulario que no permitirá que la carga use múltiples, pero debe crear un campo de entrada diferente con el mismo nombre, ya que podrá configurar el campo de agregar dinámico de la salida del archivo al hacer clic en el botón.

$ dir es el directorio en el que desea guardar la imagen $ fields es el nombre del campo que desea almacenar en la base de datos

el campo de la base de datos debe estar en el ejemplo de formato de matriz si tiene un almacén de imágenes de la base de datos y el nombre de los campos como id, nombre, dirección, entonces debe publicar datos como

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

y luego pasa ese campo a la función $ fields

$ table es el nombre de la tabla en la que desea almacenar los datos.

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 clase imageFunctions termina aquí

puede probar este código para insertar múltiples imágenes con su extensión, esta función se crea para verificar archivos de imagen, puede reemplazar la lista de extensiones para archivos perticulares en el código

Prateik Darji
fuente
Hola a todos, uso la entrada de archivo para adjuntar documentos a un correo electrónico generado automáticamente. Puedo adjuntar varios documentos a la vez, sin embargo, me gustaría adjuntar varios documentos de un directorio diferente. Actualmente, si hago esto, mi documento actualmente seleccionado es reemplazado por el nuevo documento que selecciono. Por favor, ¿cómo hago para esto? Gracias
Kunbi
-1

respuesta parcial: pear HTTP_UPLOAD puede ser útil http://pear.php.net/manual/en/package.http.http-upload.examples.php

hay un ejemplo completo para múltiples archivos

damko
fuente
1
Puede usar el paquete PEAR, pero esta tarea es bastante trivial y, a menos que necesite las características adicionales que proporciona el paquete (mensajes de error internacionalizados, validación, etc.), recomendaría usar las funciones nativas de PHP. Pero esta es solo mi opinión. :)
MitMaro el
Estoy de acuerdo contigo, por eso escribí "respuesta parcial". Pero también hago todo lo posible para reutilizar el código y, a menudo, trabajo tanto como puedo con pera (los codificadores de pera son mucho mejores que yo)
damko