Upload de imagens com PHP

Upload de arquivos é a possíbilidade de você enviar um arquivo local para o servidor através do seu navegador.

Antes de colocarmos a mão na massa e fazer o formulário, vamos primeiro ver as limitações do servidor em relação ao upload de arquivo. Por padrão o PHP limita em 2MB o tamanho máximo dos arquivos a serem enviados a ele. Para aumentar este limite, vamos editar o arquivo php.ini.

O PHP limita o tamanho através de três variváveis que são vistas abaixo.

  • memory_limit: limite máximo de memória que o PHP poderá usar para cada uma das páginas que ele gerar. Este valor tem que ser igual ou maior que o upload_max_filesize;
  • file_uploads: Diz para o PHP se os Upload estão ou não ativados;
  • upload_max_filesize: limite máximo de tamanho que o PHP aceitará upload. Se você enviar um arquivo de um BYTE a mais o PHP irá ignorar o arquivo antes que você possa manipula-lo.
Arquivo php.ini do meu PHP:
; Quantidade máxima de memória um script pode consumir
; http://php.net/memory-limit
memory_limit = 128M

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Permitir o upload de arquivos.
; http://php.net/file-uploads
file_uploads = On

; Tamanho máximo permitido para upload de arquivos.
; http://php.net/upload-max-filesize
upload_max_filesize = 128M

Upload de imagens a primeira vista pode ser até simples. Mais você deve ter um cuidado muito especial com isso. Sabe por quê?

Primeiro grande motivo é que através do upload, você esta abrindo uma porta para enviar arquivos para o servidor. E isso pode ser muito prejudicial se não tratado com carinho.

A maior parte dos ataques de hacker se da através da tentativa de enviar um arquivo .php para o servidor. Se ele conseguir enviar este arquivo ele tem acesso a muitos itens dentro do servidor.

Para enviar arquivos, você tem que definir o enctype do seu como "multipart/form-data" e o atributo method="post".  Agora temos um form que aceita enviar arquivos.

Veja abaixo um form simples:

<form method="post" enctype="multipart/form-data">
   Selecione uma imagem: <input name="arquivo" type="file" />
   <br />
   <input type="submit" value="Salvar" />
</form>

Agora temos um sistema muito simples de envio de arquivos. Usamos um <input type="file" /> para criar um campo de envio de arquivo. Veja como ficou nosso script rodando no firefox:

Agora vamos alterar o action="recebeUpload.php", para que o upload seja direcionado para a página recebeUpload.php. Veja o formulário completo:

<form method="post" enctype="multipart/form-data" action="recebeUpload.php">
   Selecione uma imagem: <input name="arquivo" type="file" />
   <br />
   <input type="submit" value="Salvar" />
</form>

Veja o exemplo rodando em /code/10031/form.html.

Agora vamos criar o arquivo recebeUpload.php.

$destino = 'imagens/' . $_FILES['arquivo']['name'];

$arquivo_tmp = $_FILES['arquivo']['tmp_name'];

move_uploaded_file( $arquivo_tmp, $destino  );

O exemplo acima funciona corretamente, mais recebe um zero em questão de segurança. Sabe porque? Ele simplesmente salva todos os arquivos que foi enviado por upload para o servidor. Se eu selecionar um arquivo .php e envia-lo ele poderá ser executado sem nenhum problema pelo servidor.

Então vamos refazer este exemplo com mais segurança

<?php
/******
 * Upload de imagens
 ******/

// verifica se foi enviado um arquivo 
if ( isset( $_FILES[ 'arquivo' ][ 'name' ] ) && $_FILES[ 'arquivo' ][ 'error' ] == 0 ) {
    echo 'Você enviou o arquivo: <strong>' . $_FILES[ 'arquivo' ][ 'name' ] . '</strong><br />';
    echo 'Este arquivo é do tipo: <strong > ' . $_FILES[ 'arquivo' ][ 'type' ] . ' </strong ><br />';
    echo 'Temporáriamente foi salvo em: <strong>' . $_FILES[ 'arquivo' ][ 'tmp_name' ] . '</strong><br />';
    echo 'Seu tamanho é: <strong>' . $_FILES[ 'arquivo' ][ 'size' ] . '</strong> Bytes<br /><br />';

    $arquivo_tmp = $_FILES[ 'arquivo' ][ 'tmp_name' ];
    $nome = $_FILES[ 'arquivo' ][ 'name' ];

    // Pega a extensão
    $extensao = pathinfo ( $nome, PATHINFO_EXTENSION );

    // Converte a extensão para minúsculo
    $extensao = strtolower ( $extensao );

    // Somente imagens, .jpg;.jpeg;.gif;.png
    // Aqui eu enfileiro as extensões permitidas e separo por ';'
    // Isso serve apenas para eu poder pesquisar dentro desta String
    if ( strstr ( '.jpg;.jpeg;.gif;.png', $extensao ) ) {
        // Cria um nome único para esta imagem
        // Evita que duplique as imagens no servidor.
        // Evita nomes com acentos, espaços e caracteres não alfanuméricos
        $novoNome = uniqid ( time () ) . '.' . $extensao;

        // Concatena a pasta com o nome
        $destino = 'imagens / ' . $novoNome;

        // tenta mover o arquivo para o destino
        if ( @move_uploaded_file ( $arquivo_tmp, $destino ) ) {
            echo 'Arquivo salvo com sucesso em : <strong>' . $destino . '</strong><br />';
            echo ' < img src = "' . $destino . '" />';
        }
        else
            echo 'Erro ao salvar o arquivo. Aparentemente você não tem permissão de escrita.<br />';
    }
    else
        echo 'Você poderá enviar apenas arquivos "*.jpg;*.jpeg;*.gif;*.png"<br />';
}
else
    echo 'Você não enviou nenhum arquivo!';

Veja este exemplo funcionando em /code/10031/form.html

Baixe os exemplos deste POST aqui.

Possui dúvidas? Escreva nos comentários.

Fique por dentro de nossas novidades, ideias e atualizações