PHP – upload de arquivos com POST

Sempre que implemento algumas coisas no And After surgem mil idéias para posts aqui no O Desenvolvedor, desta vez vou abordar como lidar com upload de arquivos com PHP através do método POST.

 

Formulário para envio de arquivo

Para permitir o upload de arquivos com PHP o formulário deve ter o atributo enctype da seguinte forma:

form enctype="multipart/form-data" action="post.php" method="post"

E o campo de arquivo, onde o usuário vai selecionar o arquivo que será submetido através do método POST"

input name="userfile" type="file"

Upload de arquivo com PHP

Na sua página PHP que receberá o post do formulário você terá acesso ao objeto $_FILES, que será um array com todos os arquivos submetidos no post.

Para acessar um arquivo específico, usamos o valor do atributo "name" que foi utilizado no inpute de arquivo no formulário, no exemplo anterior o nome é "userfile", portanto teremos $_FILES['userfile'].

Para visualizar no navegador todas as informações existentes no objeto faça o seguinte:

print_r($_FILES['userfile']);

Você terá

  • $_FILES['userfile']['name']
  • $_FILES['userfile']['type']
  • $_FILES['userfile']['size']
  • $_FILES['userfile']['tmp_name']
  • $_FILES['userfile']['error'] (veja a lista de código de erros do upload PHP)

Com estas informações você pode aplicar toda a lógica e tratamento necessário como verificação da extensão, tamanho, nomenclatura do arquivo, etc.

Perceba que o arquivo é salvo temporariamente no servidor, portanto neste ponto do código não existe nenhuma mágica, o upload já foi feito e você só precisa mover e renomear o arquivo para onde você deseja.

Função move_uploaded_file

Depois de fazer os tratamentos necessários no PHP, você pode utilizar a função move_uploaded_file para mover o arquivo para o diretório onde ele deverá ficar (veja como criar pastas em PHP).

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . $_FILES['userfile']['name'];
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $_FILES['userfile']['name'])) {
    echo "Upload com sucesso";
} else {
    echo "Erro no upload";
}
print_r($_FILES);

Espero ter ajudado no entendimento de como funciona o upload de arquivos com PHP, atualmente deixo o Code Igniter gerenciar quase tudo isso nas minhas aplicações. 🙂

Usando a Prototype – passo 4 – upload de arquivo sem post na tela

Segue abaixo um exemplo de como fazer upload de um arquivo, através de um formulário, sem precisar dar post na página.
Como funciona?
Um form normal de upload de arquivo que tem no onsubmit chamada a função javascript. Essa, por sua vez, cria um iframe em tempo de execução, muda o target do form para esse iframe e faz o upload do form.
O arquivo de destino (nesse caso usei um .php, mas independe de qual linguagem para gerenciar esse upload você quer usar) tem no onload uma chamada à função javascript do parent dele que faz informar na tela que o upload foi efetuado. Trocandando em miúdos, o upload é feito da mesma forma que sempre foi feito, e quando a página é carregada no iframe – é o momento em que o upload do arquivo foi feito e a página processada -, por javascript se faz atualizar a página pai.

Segue abaixo o código das duas páginas, comentado (usei a biblioteca Prototype para ajudar no javascript):

index.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Exemplo de upload</title>
<script src="http://www.prototypejs.org/assets/2008/1/25/prototype-1.6.0.2.js"></script>
<script type="text/javascript">
    function upload() {
        //cria um iframe, escondido
        var iframe = new Element("iframe", {name:"target", id:"iframe_upload"});
        //insere na página o iframe
        document.body.insert(iframe);
        //muda o target do form, apontando para o iframe
        $("form_upload").target = iframe.name;
        //mostra a mensagem
        $("message").update("aguarde, enviando arquivo...");
    }
   
    function closeIframe() {
        //atualiza a mensagem
        $("message").update("arquivo enviado com sucesso");
        //apaga o iframe
        $("iframe_upload").remove();
    }
</script>
<style type="text/css">
    iframe {display:none;}
</style>
</head>
<body>
<h1>Exemplo de upload</h1>
<form action="upload.php" method="post" enctype="multipart/form-data" id="form_upload" onsubmit="return upload();">
    <input type="file" name="arquivo" id="arquivo" />
    <input type="submit" value="enviar" />
    <span id="message"></span>
</form>
</body>
</html>

 

upload.php

<?php
//faz todo o processamento necessário no PHP para persistir o arquivo
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Upload - OK</title>
</head>
<!-- chama função javascript da página pai -->
<body onload="parent.closeIframe();">
</body>
</html>

Basicamente, isso é o que a maioria dos sites que têm formulários de upload estão fazendo; é o que chamam, por aí, de upload 2.0. Não sei se concordo muito com o termo usado, mas faz o mesmo efeito.
Vale ressaltar que muitas bibliotecas javascript fazem isso, inclusive com plugins bem maduros. Mas, de qualquer modo, vale a pena saber como funcionam esses plugins, entender qual a dinâmica e o conceito.
Em breve mostro outra forma de fazer upload com barra de progresso – tanto com uma linguagem server-side quanto usando Flash (e Action Script 3).