Como posso selecionar e fazer upload de vários arquivos com HTML e PHP, usando HTTP POST?

155

Tenho experiência em fazer isso com uploads de arquivo único usando <input type="file">. No entanto, estou com problemas para fazer o upload de mais de um por vez.

Por exemplo, eu gostaria de poder selecionar uma série de imagens e enviá-las ao servidor, de uma só vez.

Seria ótimo usar um controle de entrada de arquivo único, se possível.

Alguém sabe como fazer isso? Obrigado!

stalepretzel
fonte
2
Você quer dizer selecionar mais de um arquivo na caixa de diálogo do seletor de arquivos ou usar várias entradas de arquivo?
MitMaro
Olá, É possível fazer upload de um arquivo (zip, rar, tar, ...)?
22615 sourcerebels

Respostas:

196

Isso é possível no HTML5 . Exemplo (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>

Veja como é o Chrome depois de selecionar 2 itens na caixa de diálogo de arquivo:

seleção de vários arquivos do chrome

E aqui está o que parece depois de clicar no botão "Upload".

enviando vários arquivos para PHP

Este é apenas um esboço de uma resposta totalmente funcional. Consulte Manual do PHP: Manipulando uploads de arquivos para obter mais informações sobre o manuseio adequado e seguro de uploads de arquivos em PHP.

Mark E. Haase
fonte
8
passa na validação w3c ou deveria ser multiple="multiple"?
vol7ron
10
Acredito que seja válido: thoughtresults.com/html5-boolean-attributes . Ele passa o validador w3c se você adicionar <! Doctype html>.
Mark E. Haase
2
Sim, provavelmente valida o HTML, mas falha no XHTML. Embora eu ainda goste de usar o XHTML, acho que as pessoas aconselham ficar longe dele atualmente.
vol7ron
11
Não funcionou sem adicionar o nome da propriedade (por exemplo name="file[]"). Tentei editar a resposta , mas ela foi rejeitada.
Michel Ayres
1
Obrigado @MichelAyres, atualizei minha resposta. Quando eu escrevi isso originalmente, eu resolvi apenas a parte HTML do problema porque havia outras respostas que explicavam a parte PHP. Com o tempo, isso se tornou uma resposta popular, então agora eu expandi para cobrir HTML e PHP.
Mark E. Haase
94

Há algumas coisas que você precisa fazer para criar um upload de vários arquivos, na verdade é bastante básico. Você não precisa usar Java, Ajax, Flash. Basta criar um formulário de upload de arquivo normal começando com:

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

Então a chave para o sucesso;

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

NÃO esqueça esses suportes! No post_upload.php, tente o seguinte:

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

Observe que você obtém uma matriz com dados tmp_name, o que significa que você pode acessar cada arquivo com um terceiro par de colchetes com o exemplo 'number' do arquivo:

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

Você pode usar php count () para contar o número de arquivos que foram selecionados. Goodluck widdit!

Epoxys
fonte
5
Obrigado pela dica! isso me salvou muito tempo +1
BPm
Funciona muito bem ... mas estou tendo problemas para fazer o upload dessa maneira no Internet Explorer (v8). Eu acho que o IE não suporta o upload dessa maneira.
Tariq M Nasim
4
Ou você pode percorrer os arquivos com uma foreachdeclaração, sem ter que saber o número de arquivos carregados ...
ygesher
Observe que, se você usar uma chave em seu nome em seu html, por exemplo, name = "file [3]", precisará acessar o valor via $ _FILES ['file'] ['tmp_name'] [3], no caso isso não é óbvio.
MyStream
8

Solução completa no 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
fonte
O código cortado. Aqui está o que vem logo acima: <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
Porém, não funcionou no IE8, mas apenas use um navegador real.
Thaps
5

Se você deseja selecionar vários arquivos na caixa de diálogo do seletor de arquivos que é exibida quando você seleciona procurar, então não tem mais sorte. Você precisará usar um applet Java ou algo similar (acho que existe um que use um pequeno arquivo flash, atualizarei se o encontrar). Atualmente, uma entrada de arquivo único permite apenas a seleção de um único arquivo.

Se você está falando sobre o uso de várias entradas de arquivo, não deve haver muita diferença em usar uma. Poste algum código e tentarei ajudar mais.


Atualização: existe um método para usar um único botão 'navegar' que usa flash. Eu nunca usei isso pessoalmente, mas li bastante sobre isso. Eu acho que é o seu melhor tiro.

http://swfupload.org/

MitMaro
fonte
1
Eu adicionei o link para o upload múltiplo baseado em flash.
MitMaro
Eu usei o swfupload fwiw - é um pouco doloroso em algumas ocasiões, mas não é tão difícil de trabalhar.
Meep3D
@Barsoom está correto. As coisas melhoraram muito nos vários uploads de arquivos nos últimos dois anos. : D
MitMaro 24/06
4

no primeiro você deve criar uma forma como esta:

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

isso está certo . Agora, adicione esse código no código do formulário ou em qualquer página que você quiser

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

é fácil ... terminar

pooya laryan
fonte
1

Se você usar vários campos de entrada, poderá definir nome = "arquivo []" (ou qualquer outro nome). Isso os colocará em uma matriz quando você os enviar ( $_FILES['file'] = array ({file_array},{file_array]..))

Torandi
fonte
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 o loop 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}.";                               
      }                 

    }               
  }    
?>

Usando o loop 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
fonte
0

Eu criei uma função php que é usada para fazer upload de várias imagens, esta função pode fazer upload de várias imagens em uma pasta específica, além de salvar os registros no banco de dados no seguinte código $ arrayimage é o conjunto de imagens que é enviado através do formulário. que ele não permitirá que o upload use vários, mas você precisa criar um campo de entrada diferente com o mesmo nome para definir o campo de adição dinâmica da entrada de arquivo ao clicar no botão.

$ dir é o diretório no qual você deseja salvar a imagem $ fields é o nome do campo que você deseja armazenar no banco de dados

O campo do banco de dados deve estar no exemplo de formato de matriz, se você tiver um armazenamento de imagens e campos, como id, nome, endereço, será necessário postar dados como

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

e depois passe esse campo para a função $ fields

$ table é o nome da tabela na qual você deseja armazenar os dados.

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
}

// classe imageFunctions termina aqui

você pode tentar este código para inserir várias imagens com sua extensão. Essa função é criada para verificar arquivos de imagem. É possível substituir a lista de extensões por arquivos perticulares no código.

Prateik Darji
fonte
Oi pessoal, Eu uso a entrada de arquivo para anexar documentos a um email gerado automaticamente. Sou capaz de anexar vários documentos em qualquer lugar, no entanto, gostaria de anexar vários documentos de um diretório diferente. Atualmente, se eu fizer isso, meu documento atualmente selecionado é substituído pelo novo documento que seleciono. Por favor, como faço para fazer isso. Obrigado
Kunbi
-1

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

existe um exemplo completo para vários arquivos

damko
fonte
1
Você pode usar o pacote PEAR, mas essa tarefa é bastante trivial e, a menos que você precise dos recursos extras que o pacote fornece (mensagens de erro internacionalizadas, validação, etc.), eu recomendaria o uso das funções nativas do PHP. Mas esta é apenas a minha opinião. :)
MitMaro
Eu concordo com você, foi por isso que escrevi "resposta parcial". Mas eu também faço o meu melhor para reutilização de código e muitas vezes eu trabalho tanto quanto eu posso com pêra (codificadores de pêra são muito mais melhor do que eu :-D)
damko