+3

Formulários e upload de múltiplos arquivos com PHP

criado por Alfred R. Baudisch em 24/12/2006 9:35pm
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
<?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 &eacute; definida a pasta para onde ir&atilde;o as fotos.

<font color="red">B)</font> Obt&eacute;m-se o array de fotos enviadas, passando para a vari&aacute;vel $Fotos. O ponto chave &eacute; que o PHP transforma um campo de formul&aacute;rio nome[] em um array de sub-arrays para cada um dos ind&iacute;ces (name, type, size, tmp_name e error).

Exemplificando:
a) Quando &eacute; apenas um campo, digamos, documento, o PHP cria o array:
$_FILES['documento'], que por sua vez &eacute; um array que cont&eacute;m os &iacute;ndices:
- name, size, tmp_name, type e error.

b) O PONTO PRINCIPAL DO ARTIGO: Quando &eacute; um campo array, fotos[], e digamos que tenham sido enviadas 2 fotos, o PHP cria um array $_FILES[&lsquo;fotos&rsquo;], contendo os mesmo &iacute;ndices de sempre, mas cada indice desse &eacute; um novo array, cada uma com a informa&ccedil;&atilde;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&atilde;o m&uacute;ltiplos envios a vari&aacute;vel que identifica o campo de upload &eacute; a mesma quando &eacute; um arquivo, acontece que cada &iacute;ndice &eacute; 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&ccedil;&otilde;es do upload est&atilde;o num array, &eacute; iterado normalmente por ela (usando um loop for) como se fosse um outro array qualquer!

<font color="red">D)</font> Para cada &iacute;ndice, &eacute; passado o valor da itera&ccedil;&atilde;o para novas vari&aacute;veis: $Nome, $Tamanho, $Tipo e $Tmpname, que cont&ecirc;m informa&ccedil;&otilde;es diretas sobre o arquivo, como se fosse o upload de um s&oacute; 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 &eacute; uma imagem (atrav&eacute;s da checagem de MIME/TYPE &ndash; caso queira enviar um documento, basta mudar esse tupo de checagem). Assim, caso &ldquo;aprovada&rdquo; &eacute; copiada para a pasta desejada (em F).

Assim, move-se para a pr&oacute;xima foto (pr&oacute;ximo item do array $Fotos).

ATEN&Ccedil;&Atilde;O: Note que s&oacute; entra nos pr&oacute;ximos passos, caso verificado que tenha sido enviado um arquivo naquele campo, atrav&eacute;s do if (verificando tamanho e nome) :

if($Tamanho > 0 && strlen($Nome) > 1)

Pois como &eacute; um array de campos, se forem 10 campos, mas o usu&aacute;rio colocar algum arquivo em s&oacute; 2 deles, de qualquer forma o PHP retornar&aacute; um array com 10 itens. Por isso, &eacute; importante certificar de que realmente foi enviado arquivo naquela itera&ccedil;&atilde;o.

Por exemplo: se o usu&aacute;rio enviar uma foto no campo 1 e somente outra no campo 5, os dados ser&atilde;o enviados corretamente devido &agrave; checagem de envio.

Comentários:

Mostrando 1 - 10 de 13 comentários
Muito bom! Obrigado!!
28/09/2011 5:41pm (~12 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?
16/02/2009 7:25am (~15 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 (~15 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
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.
29/01/2007 4:38am (~17 anos atrás)

show de bola o artigo!
24/01/2007 12:20pm (~17 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 (~17 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)