Formulários e upload de múltiplos arquivos com PHP
3) Processamento do upload
O nosso arquivo de processamento do formulário é o processa_upload.php. O que ele faz é obter o campo de upload, que é um array, e iterar sobre esse array fazendo a validação e o envio arquivo por arquivo, de acordo com o que estiver no array:
processa_upload.php
<font color="red">A)</font> Primeiro é definida a pasta para onde irão as fotos.
<font color="red">B)</font> Obtém-se o array de fotos enviadas, passando para a variável $Fotos. O ponto chave é que o PHP transforma um campo de formulário nome[] em um array de sub-arrays para cada um dos indíces (name, type, size, tmp_name e error).
Exemplificando:
a) Quando é apenas um campo, digamos, documento, o PHP cria o array:
$_FILES['documento'], que por sua vez é um array que contém os índices:
- name, size, tmp_name, type e error.
b) O PONTO PRINCIPAL DO ARTIGO: Quando é um campo array, fotos[], e digamos que tenham sido enviadas 2 fotos, o PHP cria um array $_FILES[‘fotos’], contendo os mesmo índices de sempre, mas cada indice desse é um novo array, cada uma com a informação de cada uma das fotos:
Deu para entender? Quando são múltiplos envios a variável que identifica o campo de upload é a mesma quando é um arquivo, acontece que cada índice é um novo array, de acordo com a quantidade de campos de upload. Se eu quero saber o nome e tamanho do segundo arquivo, simplesmente atuo num array normalmente:
$_FILES['fotos']['name'][0];
$_FILES['fotos']['size'][0];
<font color="red">C)</font> Como as informações do upload estão num array, é iterado normalmente por ela (usando um loop for) como se fosse um outro array qualquer!
<font color="red">D)</font> Para cada índice, é passado o valor da iteração para novas variáveis: $Nome, $Tamanho, $Tipo e $Tmpname, que contêm informações diretas sobre o arquivo, como se fosse o upload de um só arquivo:
$Foto['name'] = nome do arquivo
$Foto['size'] = tamanho em bytes do arquivo
$Foto['type'] = MIME Type do arquivo
$Foto['tmp_name'] = local do upload, para usar na função move_uploaded_file
$Foto['error'] = código de erro, não usado nesse artigo
<font color="red">E)</font> Verifica se é uma imagem (através da checagem de MIME/TYPE – caso queira enviar um documento, basta mudar esse tupo de checagem). Assim, caso “aprovada” é copiada para a pasta desejada (em F).
Assim, move-se para a próxima foto (próximo item do array $Fotos).
ATENÇÃO: Note que só entra nos próximos passos, caso verificado que tenha sido enviado um arquivo naquele campo, através do if (verificando tamanho e nome) :
if($Tamanho > 0 && strlen($Nome) > 1)
Pois como é um array de campos, se forem 10 campos, mas o usuário colocar algum arquivo em só 2 deles, de qualquer forma o PHP retornará um array com 10 itens. Por isso, é importante certificar de que realmente foi enviado arquivo naquela iteração.
Por exemplo: se o usuário enviar uma foto no campo 1 e somente outra no campo 5, os dados serão enviados corretamente devido à checagem de envio.
O nosso arquivo de processamento do formulário é o processa_upload.php. O que ele faz é obter o campo de upload, que é um array, e iterar sobre esse array fazendo a validação e o envio arquivo por arquivo, de acordo com o que estiver no array:
processa_upload.php
<?php // A) Pasta de destino das fotos $Destino = './eventoxyz/fotos/'; // B) Obtém dados do upload $Fotos = $_FILES['fotos']; // Contagem de fotos enviadas $Conta = 0; // C) Itera sobre as enviadas e processa as validações e upload for($i = 0; $i < sizeof($Fotos); $i++) { // D) Passa valores da iteração atual $Nome = $Fotos['name'][$i]; $Tamanho = $Fotos['size'][$i]; $Tipo = $Fotos['type'][$i]; $Tmpname = $Fotos['tmp_name'][$i]; // Verifica se tem arquivo enviado if($Tamanho > 0 && strlen($Nome) > 1) { // E) Verifica se é uma imagem if(preg_match('/^image\/(gif|jpeg|jpg|png)$/', $Tipo)) { // Caminho completo de destino da foto $Caminho = $Destino . $Nome; // F) Tudo OK! Move o upload! if(move_uploaded_file($Tmpname, $Caminho)) { echo 'Foto #' . ($i+1) . ' enviada.<br/>'; // Faz contagem de enviada com sucesso $Conta++; } else // Erro no envio { // $i+1 porque $i começa em zero echo 'Não foi possível enviar a foto #' . ($i+1) . '<br/>'; } } } } if($Conta) // Imagens foram enviadas, ok! { echo '<br/>Foi(am) enviada(s) ' . $Conta . ' foto(s).'; } else // Nenhuma imagem enviada, faz alguma ação { echo 'Você não enviou fotos!'; } ?>
<font color="red">A)</font> Primeiro é definida a pasta para onde irão as fotos.
<font color="red">B)</font> Obtém-se o array de fotos enviadas, passando para a variável $Fotos. O ponto chave é que o PHP transforma um campo de formulário nome[] em um array de sub-arrays para cada um dos indíces (name, type, size, tmp_name e error).
Exemplificando:
a) Quando é apenas um campo, digamos, documento, o PHP cria o array:
$_FILES['documento'], que por sua vez é um array que contém os índices:
- name, size, tmp_name, type e error.
b) O PONTO PRINCIPAL DO ARTIGO: Quando é um campo array, fotos[], e digamos que tenham sido enviadas 2 fotos, o PHP cria um array $_FILES[‘fotos’], contendo os mesmo índices de sempre, mas cada indice desse é um novo array, cada uma com a informação de cada uma das fotos:
<?php $_FILES['fotos'] = array( 'name' => array('nome1.jpg', 'nome2.jpg'), 'size' => array(12345, 53223), 'tmp_name' => array('dir/bla/img.tmp', 'dir/bla/img2.tmp'), 'error' => array(0, 0) );
Deu para entender? Quando são múltiplos envios a variável que identifica o campo de upload é a mesma quando é um arquivo, acontece que cada índice é um novo array, de acordo com a quantidade de campos de upload. Se eu quero saber o nome e tamanho do segundo arquivo, simplesmente atuo num array normalmente:
$_FILES['fotos']['name'][0];
$_FILES['fotos']['size'][0];
<font color="red">C)</font> Como as informações do upload estão num array, é iterado normalmente por ela (usando um loop for) como se fosse um outro array qualquer!
<font color="red">D)</font> Para cada índice, é passado o valor da iteração para novas variáveis: $Nome, $Tamanho, $Tipo e $Tmpname, que contêm informações diretas sobre o arquivo, como se fosse o upload de um só arquivo:
$Foto['name'] = nome do arquivo
$Foto['size'] = tamanho em bytes do arquivo
$Foto['type'] = MIME Type do arquivo
$Foto['tmp_name'] = local do upload, para usar na função move_uploaded_file
$Foto['error'] = código de erro, não usado nesse artigo
<font color="red">E)</font> Verifica se é uma imagem (através da checagem de MIME/TYPE – caso queira enviar um documento, basta mudar esse tupo de checagem). Assim, caso “aprovada” é copiada para a pasta desejada (em F).
Assim, move-se para a próxima foto (próximo item do array $Fotos).
ATENÇÃO: Note que só entra nos próximos passos, caso verificado que tenha sido enviado um arquivo naquele campo, através do if (verificando tamanho e nome) :
if($Tamanho > 0 && strlen($Nome) > 1)
Pois como é um array de campos, se forem 10 campos, mas o usuário colocar algum arquivo em só 2 deles, de qualquer forma o PHP retornará um array com 10 itens. Por isso, é importante certificar de que realmente foi enviado arquivo naquela iteração.
Por exemplo: se o usuário enviar uma foto no campo 1 e somente outra no campo 5, os dados serão enviados corretamente devido à checagem de envio.
Muito bom! Obrigado!!
28/09/2011 5:41pm
(~13 anos atrás)
O problema dos 2MB de limite de upload deve-se ao facto das configurações do PHP estarem definidas para esse valor.
No ficheiro php.ini normalmente tem essa propriedade upload_max_filesize = 2M
Tente alterar para ver como resulta.
Estou com o mesmo problema das 5 fotos, qualquer que seja o valor que eu coloque na quantidade o tamanho do array é sempre 5 e dai nao deixar enviar mais de 5 fotos.
Alguma solução para isto? Ou é uma limitação do servidor?
No ficheiro php.ini normalmente tem essa propriedade upload_max_filesize = 2M
Tente alterar para ver como resulta.
Estou com o mesmo problema das 5 fotos, qualquer que seja o valor que eu coloque na quantidade o tamanho do array é sempre 5 e dai nao deixar enviar mais de 5 fotos.
Alguma solução para isto? Ou é uma limitação do servidor?
16/02/2009 7:25am
(~16 anos atrás)
Adorei mesmo ^^ perfeito coloquei pra faze upload de um monte de arquivo agora parece rapidshare =D muito útil mesmo Obrigado.
13/10/2008 5:16pm
(~16 anos atrás)
alterei o script para permitir outros tipos de arquivos...consegui fazer o upload deles (.doc,.xls,.exe) porém não consigo postar arquivos com tamanho grandes ....acho q com + de 2 MB já da pau!!! Como faço para resolver isso??? é alguma configuração de servidor??? do Php???
05/03/2008 2:14pm
(~16 anos atrás)
quando envio os arquivos ... ele faz td certinho mas só consegue enviar 5 fotos independente do numero da quantidade que eu colocar ... tem alguma explicacao pra isso???
21/06/2007 9:43am
(~17 anos atrás)
Ficou muito bom mesmo esse script, pra quem esta aprendendo como eu então é dez, todo explicadinho muito bom mesmo, mas estou com um problema, quando envio a foto aparece uma mensagem dizendo: "Você não enviou foto" porque aparece a mensagem?
27/05/2007 3:07pm
(~17 anos atrás)
Respondendo a gundes.rs e lacertae
Já me perguntei também se existe como selecionar uma pasta ou diversos arquivos de uma vez. Pois para o usuario é realmente insuportável, digamos, ter que selecionar 500 arquivos um a um para armazenar num sistema de GED por exemplo.
Ai pesquisando descobri uma solução usando flash, não sou amigo de flash, mais num caso extremo como este, até largo mão de meus preconceitos. O produto não és free, mais fica a dica:
http://www.element-it.com/DemoMultiPOW.aspx
O produto, permite que a interface que irá efetuar a persistencia dos arquivos no servidor, seja desenvolvida ao gosto do cliente (asp/php/perl)
No site tem um demo.
Um abraço a todos
Já me perguntei também se existe como selecionar uma pasta ou diversos arquivos de uma vez. Pois para o usuario é realmente insuportável, digamos, ter que selecionar 500 arquivos um a um para armazenar num sistema de GED por exemplo.
Ai pesquisando descobri uma solução usando flash, não sou amigo de flash, mais num caso extremo como este, até largo mão de meus preconceitos. O produto não és free, mais fica a dica:
http://www.element-it.com/DemoMultiPOW.aspx
O produto, permite que a interface que irá efetuar a persistencia dos arquivos no servidor, seja desenvolvida ao gosto do cliente (asp/php/perl)
No site tem um demo.
Um abraço a todos
27/03/2007 5:45pm
(~17 anos atrás)
É, muito legal o script. Creio que vai ajudar muita gente. Tenho uns sistemas desenvolvidos assim. Mas o meus clientes sempre pergutam o mesmo que o amigo acima perguntou : É possível pegar todos os arquivos de uma pasta ? Ou os selecionados ?
Realmente é chato, num postador de fotos por exemplo, vc vai catando uma por uma...pra depois ENVIAR. Isso poderia ser resolvido selecionando vinte de vez, ou o que estiver na pasta. Desde que não sobrecarregue ou que tenha um limite.
Eis o DESAFIO !!..rsr.
Realmente é chato, num postador de fotos por exemplo, vc vai catando uma por uma...pra depois ENVIAR. Isso poderia ser resolvido selecionando vinte de vez, ou o que estiver na pasta. Desde que não sobrecarregue ou que tenha um limite.
Eis o DESAFIO !!..rsr.
29/01/2007 4:38am
(~18 anos atrás)
boam dia Alfred, gostei do seu script, na minha máquina ele unciona perfeitamente, mais quando coloquei no servidor, ele não envia, sabe me dizer porque??
19/01/2007 4:02am
(~18 anos atrás)