ULTIMATE PHP Blog

Conheça 15 Ferramentas Essenciais Para PHP
15 Ferramentas Essenciais Para PHP

Coloque seu e-mail abaixo e baixe agora um PDF 100% gratuito mostrando 15 ferramentas indispensáveis para PHP

Fique tranquilo. Odeio spam tanto quanto você :)

Upload Múltiplo de Arquivos com PHP

Upload Múltiplo de Arquivos com PHP

No artigo anterior, falei sobre upload de arquivo com PHP. Desta vez, vou falar sobre upload múltiplo.

Dando continuidade no assunto, e aprimorando mais a ideia, neste artigo vou mostrar como fazer upload múltiplo, enviando diversos arquivos de uma só vez.

Caso não tenha lido ainda o artigo sobre upload, clique aqui para lê-lo.

A Diretiva max_file_uploads do php.ini

Uma diretiva do php.ini afeta diretamente o upload de múltiplos arquivos no PHP: a max_file_uploads.

Essa diretiva diz qual é o número máximo de arquivos que podem ser enviados de uma só vez.

O valor padrão dessa diretiva é 20 e, ao contrário de post_max_size e upload_max_filesize, que comentei no artigo sobre upload, max_file_uploads não pode ser alterada pelo .htaccess, apenas no php.ini ou no httpd.conf do Apache.

Formulário HTML

Vamos ao formulário. É praticamente igual, só mudei a linha do input, cujo name passou a ser arquivos[] e também recebeu o atributo multiple. Assim, é possível selecionar vários arquivos de uma vez, para fazer upload múltiplo.

Os colchetes no atributo name forçam o PHP a tratar o valor como array.

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Upload Múltiplo de arquivos</title>
    </head>
    <body>
        <h1>Upload Múltiplo de Arquivos com PHP</h1>
        
        <form action="upload.php" method="post" enctype="multipart/form-data">
            <input type="file" name="arquivos[]" multiple>
            <br>
            <input type="submit" value="Enviar">
        </form>
    </body>
</html>

Script de Upload

No upload.php, apenas dê um print_r em $_FILES, para ver como esse array é gerado.

<?php
print_r($_FILES);

Ao enviar 3 arquivos, o resultado será o parecido com este:

Array
(
    [arquivos] => Array
        (
            [name] => Array
                (
                    [0] => imagem.png
                    [1] => documento.doc
                    [2] => arquivo.pdf
                )

            [type] => Array
                (
                    [0] => image/png
                    [1] => application/msword
                    [2] => application/pdf
                )

            [tmp_name] => Array
                (
                    [0] => /private/var/folders/pf/yk80714j0s715klrrzm38_f80000gn/T/phpz9ofF0
                    [1] => /private/var/folders/pf/yk80714j0s715klrrzm38_f80000gn/T/phpfQmVLO
                    [2] => /private/var/folders/pf/yk80714j0s715klrrzm38_f80000gn/T/phpK8mRB6
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                    [2] => 0
                )

            [size] => Array
                (
                    [0] => 249370
                    [1] => 188451
                    [2] => 8735757
                )
        )
)

A única coisa que muda é que cada um dos índices gerados pelo PHP (name, tmp_name etc) passou a ser um array, correspondendo a cada um dos arquivos enviados.

Portanto, para fazer upload múltiplo, a lógica do envio é parecida com a do upload único, mas ela deverá ficar dentro de um loop.

Vamos ao script completo:

<?php

// diretório de destino do arquivo
define('DEST_DIR', __DIR__ . '/arquivos');

if (isset($_FILES['arquivos']) && !empty($_FILES['arquivos']['name']))
{
    // se o "name" estiver vazio, é porque nenhum arquivo foi enviado
    
    // cria uma variável para facilitar
    $arquivos = $_FILES['arquivos'];

    // total de arquivos enviados
    $total = count($arquivos['name']);

    for ($i = 0; $i < $total; $i++)
    {
        // podemos acessar os dados de cada arquivo desta forma:
        // - $arquivos['name'][$i]
        // - $arquivos['tmp_name'][$i]
        // - $arquivos['size'][$i]
        // - $arquivos['error'][$i]
        // - $arquivos['type'][$i]
        
        if (!move_uploaded_file($arquivos['tmp_name'][$i], DEST_DIR . '/' . $arquivos['name'][$i]))
        {
            echo "Erro ao enviar o arquivo: " . $arquivos['name'][$i];
        }
    }

    echo "Arquivos enviados com sucesso";
}

Esse script envia os arquivos e os salva com seus nomes originais.

Como eu expliquei no artigo de upload único, o ideal é gerar nomes únicos para cada arquivo, para evitar que um usuário sobrescreva o de outro, ao enviar um arquivo com o mesmo nome.

E aí, o que achou do artigo? Deixe sua opinião ou dúvida aqui nos comentários!

Bons estudos!

 

Aprenda Ainda Mais

15 Dicas, Boas Práticas e Fundamentos do PHP

Conheça Dicas FUNDAMENTAIS para programar em PHP de forma Profissional

Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!

Baixe gratuitamente este guia com 15 Dicas de PHP

Sobre Roberto Beraldo
Desenvolvedor Web desde 2007, com foco em PHP. Criador do Curso ULTIMATE PHP e autor do Blog do Beraldo (rberaldo.com.br), onde compartilha dicas sobre PHP e Programação em geral.
  • Alexandre Buozi

    Parabéns pelo Tutorial, sempre acompanho seu blog.
    Tenho uma duvida…veja se pode me ajudar.
    Preciso fazer o upload multiplo, jogando a imagem com nome unico na diretorio (isso ja esta ok), mas tambem queria salvar o nome no banco de dados.
    Pode me ajudar?

  • PauloN

    Parabéns pelo tutorial, funcionou perfeitamente.

    Mas eu precisaria que tivesse um filtro apenas para imagens, mas não consegui pois não tenho muito conhecimento php. Como ficaria este mesmo código com um filtro para imagens jpg?

    Abraço e obrigado.

    • Olá, PauloN. Obrigado!
      Para fazer o filtro, você pode limitar no input file e também na programação.
      No input: https://www.w3schools.com/tags/att_input_accept.asp
      Na programação, basta validar o mime-type de cada arquivo. Você pode fazer isso usando preg_match com expressões regulares.
      Algo assim:

      if (!preg_match(“/^image/(jpe?g|gif|png)$/iu”, $mimetype))
      {
      // arquivo não permitido
      }

      • PauloN

        Obrigado pela resposta Roberto.
        Consegui colocar no input, mas no php realmente não sei onde inserir essa linha de código que você enviou. :/
        Onde ela seria inserida no código acima?
        Obrigado! 🙂

        • Você tem que verificar o tipo de cada arquivo dentro do loop, antes de chamar move_uploaded_file.
          Use o valor de $arquivos[‘type’][$i] no preg_match()

  • betobto

    Mto bons seus artigos… estou aprendendo muito…
    Uma dúvida como eu gravo os multiplos arquivos no banco de dados? tenho q criar uma tabela somente para eles?
    Obrigado

  • Angelo Augusto

    Muito bacana
    obrigado por compartilhar o conhecimento.
    Parabéns belas dicas

  • Davi Bernardo Junior

    otimo conteudo mto claro e objetivo aprendi mto com seu blog continue assim

  • Pingback: Upload de Arquivo com PHP - ULTIMATE PHP Blog()