[editado]
Uma versão mais recente e explicativa sobre Upload Múltiplo pode ser vista neste meu artigo no ULTIMATE PHP Blog
- Beraldo
[/editado]
Olá, pessoal.
Vejo muitas dúvidas sobre upload múltiplo de arquivos. Há vários scripts prontos, mas achei que seria interessante criar um artigo para mostrar como esse processo ocorre, a fim de evitar o tradicional CTRL + C CTRL + V. :D
Antes de tudo, recomendo ler o capítulo sobre uploads do Manual do PHP:
http://www.php.net/manual/pt_BR/features.file-upload.php
Comecemos pelo formulário. Dois pontos importantes devem ser ressaltados:
O atributo enctype sempre deve estar presente num formulário de upload. Caso contrário, o(s) arquivo(s) não será(ão) enviado(s);
Como estamos trabalhando ocm upload múltiplo, devemos definir o atributo name do input file semelhantemente a um array: arquivo[]. Dessa forma, o PHP interpretará $_FILES['arquivo'] como sendo um array. Assim, não importa o número de arquivos enviados. Tanto faz enviar um ou vinte arquivos; a forma de tratar o upload é a mesma.
form.html
<form name="upload" id="upload" action="upload.php" method="post" enctype="multipart/form-data">
<ul>
<li>
<input type="file" name="arquivo[]" />
</li>
<li>
<input type="file" name="arquivo[]" />
</li>
<li>
<input type="file" name="arquivo[]" />
</li>
<li>
<input type="submit" value="Enviar" />
</li>
</ul>
</form>
Inseri somente três campos, mas poderia haver dez, vinte ou mais.
Antes de começarmos a manipular os arquivos, vamos ver como o PHP gera o array $_FILES. Para isso, no arquivo upload.php, insira este código:
upload.php
<?php
echo "<pre>";
print_r($_FILES);
echo "</pre>";
?>
O resultado será:
Array
(
[arquivo] => Array
(
[name] => Array
(
[0] => arquivo1.txt
[1] => arquivo2.txt
[2] => arquivo3.txt
)
[type] => Array
(
[0] => text/plain
[1] => text/plain
[2] => text/plain
)
[tmp_name] => Array
(
[0] => C:\WINDOWS\TEMP\php8.tmp
[1] => C:\WINDOWS\TEMP\php9.tmp
[2] => C:\WINDOWS\TEMP\phpA.tmp
)
[error] => Array
(
[0] => 0
[1] => 0
[2] => 0
)
[size] => Array
(
[0] => 621
[1] => 455
[2] => 579
)
)
)
O arquivo de upload:
upload.php
<?php
// diretório de destino dos arquivos enviados
// a constante DIRECTORY_SEPARATOR contém o separador de diretório padrão de cada Sistema Operacional
$dir = 'uploads' . DIRECTORY_SEPARATOR;
// Para facilitar, atribuimos a $arquivo o valor $_FILES['arquivo']
// sobre o operador ternário: http://www.php.net/manual/pt_BR/language.operators.comparison.php
$arquivo = isset($_FILES['arquivo']) ? $_FILES['arquivo'] : FALSE;
// no count(), tanto faz colocar $arquivo['name'], $arquivo['size']
// ou outro índice gerado, pois todos têm o mesmo número de chaves.
for ($i = 0; $i < count($arquivo['name']); $i++)
{
if (move_uploaded_file($arquivo['tmp_name'][$i], $dir . $arquivo['name'][$i]))
{
echo "<p><strong>Enviado: </strong> " . $arquivo['name'][$i] . " | " . round($arquivo['size'][$i] / 1024, 2) . " kB | " . $arquivo['type'][$i] . "</p>";
}
else
{
echo "<p><strong>Não enviado: </strong> " . $arquivo['name'][$i] . " | " . round($arquivo['size'][$i] / 1024, 2) . " kB | " . $arquivo['type'][$i] . "</p>";
}
}
?>
1 kB = 1024 bytes, por isso usei 1024 e não 1000. 24 bytes parecem insignificantes, mas não são, mesmo para um arquivo pequeno. Veja:
50 kB = 50 * 1024 = 51200 != 50000
900 kB = 900 * 1024 = 921600 bytes != 900000
Por isso convém definir o tamanho máximo dos arquivos sempre da forma mostrada acima: multiplicando o tamanho máximo, em kB, por 1024, a fim de obter o valor exato.
A vantagem de criar scripts assim é que o número de arquivos não importa. Faça o teste com somente um campo file. Verá que também funciona. Ou seja, um script com essa estrutura envia um, dois, dez ou quantos arquivos forem necessários. :D
O código que mostrei não possui nenhuma validação de tipo, tamanho, erro etc, pois esse não é o foco do artigo. Quero apenas demonstrar como manipular o envio dos arquivos. As verificações são apresentadas em diversos outros artigos. Basta adicioná-las dentro do loop.
Abraços,
Beraldo