Publicidade (Anuncie Aqui)

Upload de Arquivos – Como tudo funciona

Upload de Arquivos – Como tudo funciona

Hoje resolvi falar um pouquinho mais sobre como o upload de arquivos funciona, passo a passo, onde cada coisa se encaixa e como você pode ter total controle dele.

Como exemplo usarei um formulário onde o visitante enviará o seu nome e uma foto para um “perfil” de um rede social.

1.0 – O formulário HTML

Todo upload, geralmente, começa com um formulário onde o usuário insere o arquivo que será enviado e manipulado para o servidor. Veja o nosso exemplo de formulário:

<form method="post" action="recebe.php" enctype="multipart/form-data">
<fieldset>
	<label for="txNome">Seu nome</label>
	<input type="text" name="nome" id="txNome" />

	<label for="txFoto">Sua foto</label>
	<input type="file" name="arquivo" id="txFoto" />

	<input type="submit" value="Salvar Dados" />
</fieldset>
</form>

É um formulário simples, com dois campos e um submit… O que importa nesse formulário são três coisas:

  • A propriedade action do formulário (linha 1)

    No action do formulário você especifica para qual endereço você está enviando os dados… Se você não definir essa propriedade os dados serão enviados para o mesmo endereço do formulário

  • A propriedade enctype do formulário (linha 1)

    Você precisa definir o enctype como “multipart/form-data” para o upload funcionar, caso contrário você não vai poder manipular os arquivos

  • A propriedade name do input file (linha 7)

    É nesse campo que você irá enviar o arquivo para ser manipulado pelo PHP… E é a propriedade name que você irá usar, no PHP, para saber de qual arquivos estamos falando

2.0 – Manipulando o upload no arquivo recebe.php

Agora iremos construir o arquivo recebe.php passo a passo para você entender o que acontece quando enviamos um arquivo por upload.

Normalmente quando enviamos dados através de um formulário (com a propriedade method igual a post) esses dados são disponibilizados em uma variável $_POST… Então, no começo do arquivo, iremos arquivar o nome do usuário em uma nova variável:

<?php

	$nome = $_POST['nome'];

?>

Só pra lembrar: $_POST é um array e os seus índices serão as propriedades “name” dos inputs.

2.1 – A variável $_FILES

Ao enviar um arquivo pelo formulário acima é criada uma nova variável (além da $_POST) que é chamada $_FILES… Essa variável funciona da mesma forma que a $_POST e é identificada pela propriedade name do input. A diferença é que o $_FILES traz várias informações sobre o arquivo enviado.

Veja um exemplo onde pegamos todas essas informações e salvamos em novas variáveis:

<?php

	$nome = $_POST['nome'];

	// O nome original do arquivo no computador do usuário
	$arqName = $_FILES['arquivo']['name'];
	// O tipo mime do arquivo. Um exemplo pode ser "image/gif"
	$arqType = $_FILES['arquivo']['type'];
	// O tamanho, em bytes, do arquivo
	$arqSize = $_FILES['arquivo']['size'];
	// O nome temporário do arquivo, como foi guardado no servidor
	$arqTemp = $_FILES['arquivo']['tmp_name'];
	// O código de erro associado a este upload de arquivo
	$arqError = $_FILES['arquivo']['error'];

?>

Preste atenção que a parte ['arquivo'] se deve a propriedade name do input file no lá formulário HTML.

2.2 – Erros de upload

Quando algo der errado com o upload em questão você vai poder verificar o que aconteceu baseando-se no valor da variável $_FILES['arquivo']['error']… Quando ela for diferente de zero é que algo de errado aconteceu e você pode verificar aqui possíveis valores de erro no upload.

2.3 – Movendo o arquivo para a pasta certa

Agora iremos mover o arquivo para a pasta correta caso o upload tenha ocorrido sem problemas:

<?php

	$nome = $_POST['nome'];

	// O nome original do arquivo no computador do usuário
	$arqName = $_FILES['arquivo']['name'];
	// O tipo mime do arquivo. Um exemplo pode ser "image/gif"
	$arqType = $_FILES['arquivo']['type'];
	// O tamanho, em bytes, do arquivo
	$arqSize = $_FILES['arquivo']['size'];
	// O nome temporário do arquivo, como foi guardado no servidor
	$arqTemp = $_FILES['arquivo']['tmp_name'];
	// O código de erro associado a este upload de arquivo
	$arqError = $_FILES['arquivo']['error'];

	if ($arqError == 0) {
		$pasta = '/uploads/';
		$upload = move_uploaded_file($arqTemp, $pasta . $arqName);
	}

?>

Com isso, após verificar se não houve nenhum erro, iremos mover o arquivo que está na pasta temporária do PHP para a pasta /uploads/ do seu site.

A função move_uploaded_file() usa dois argumentos: o primeiro é o nome do arquivo temporário e o segundo é local onde o arquivo será salvo (incluindo seu novo nome)… No caso usamos o nome original do arquivo, mas caso você queira renomear o arquivo é exatamente nessa linha (18) que você deve fazer isso.

Depois do upload a variável $upload terá um valor lógico (true ou false) que indica se o arquivo foi movido com sucesso ou não.

Nosso upload já está pronto… O problema é que ele aceita qualquer tipo de arquivo e não é isso que queremos.

3.0 – Validando o tipo de arquivo enviado

Usando a variável $arqType poderemos identificar qual é o tipo do arquivo… Esse tipo é chamado de mime-type.

Vamos criar uma lista com todos os mime-types permitidos e verificar se foi enviado um arquivo com o tipo correto:

<?php
	// Lista de tipos de arquivos permitidos
	$tiposPermitidos= array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png');

	$nome = $_POST['nome'];

	// O nome original do arquivo no computador do usuário
	$arqName = $_FILES['arquivo']['name'];
	// O tipo mime do arquivo. Um exemplo pode ser "image/gif"
	$arqType = $_FILES['arquivo']['type'];
	// O tamanho, em bytes, do arquivo
	$arqSize = $_FILES['arquivo']['size'];
	// O nome temporário do arquivo, como foi guardado no servidor
	$arqTemp = $_FILES['arquivo']['tmp_name'];
	// O código de erro associado a este upload de arquivo
	$arqError = $_FILES['arquivo']['error'];

	if ($arqError == 0) {
		// Verifica o tipo de arquivo enviado
		if (array_search($arqType, $tiposPermitidos) === false) {
			echo 'O tipo de arquivo enviado é inválido!';
		// Não houveram erros, move o arquivo
		} else {
			$pasta = '/uploads/';
			$upload = move_uploaded_file($arqTemp, $pasta . $arqName);
		}
	}

?>

Se precisar você ver aqui uma lista de mime-types usados por cada tipo de arquivo.

4.0 – Validando o tamanho do arquivo enviado

Muita gente tem problemas com o tamanho de arquivo enviado pelos usuários pois, dependendo da quantidade e do tipo de arquivo, você rapidamente vai ter GBs e GBs de lixo no seu servidor. Se quiser fazer essa validação, é só fazer assim:

<?php
	// Lista de tipos de arquivos permitidos
	$tiposPermitidos= array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png');
	// Tamanho máximo (em bytes)
	$tamanhoPermitido = 1024 * 500; // 500 Kb

	$nome = $_POST['nome'];

	// O nome original do arquivo no computador do usuário
	$arqName = $_FILES['arquivo']['name'];
	// O tipo mime do arquivo. Um exemplo pode ser "image/gif"
	$arqType = $_FILES['arquivo']['type'];
	// O tamanho, em bytes, do arquivo
	$arqSize = $_FILES['arquivo']['size'];
	// O nome temporário do arquivo, como foi guardado no servidor
	$arqTemp = $_FILES['arquivo']['tmp_name'];
	// O código de erro associado a este upload de arquivo
	$arqError = $_FILES['arquivo']['error'];

	if ($arqError == 0) {
        // Verifica o tipo de arquivo enviado
		if (array_search($arqType, $tiposPermitidos) === false) {
			echo 'O tipo de arquivo enviado é inválido!';
		// Verifica o tamanho do arquivo enviado
		} else if ($arqSize > $tamanhoPermitido) {
			echo 'O tamanho do arquivo enviado é maior que o limite!';
		// Não houveram erros, move o arquivo
		} else {
			$pasta = '/uploads/';
			$upload = move_uploaded_file($arqTemp, $pasta . $arqName);
		}
	}

?>

5.0 – Renomeando o arquivo enviado

Caso você queira armazenar o arquivo enviado com outro nome, mas manter a extensão do mesmo, é só fazer assim:

<?php
	// Lista de tipos de arquivos permitidos
	$tiposPermitidos= array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png');
	// Tamanho máximo (em bytes)
	$tamanhoPermitido = 1024 * 500; // 500 Kb

	$nome = $_POST['nome'];

	// O nome original do arquivo no computador do usuário
	$arqName = $_FILES['arquivo']['name'];
	// O tipo mime do arquivo. Um exemplo pode ser "image/gif"
	$arqType = $_FILES['arquivo']['type'];
	// O tamanho, em bytes, do arquivo
	$arqSize = $_FILES['arquivo']['size'];
	// O nome temporário do arquivo, como foi guardado no servidor
	$arqTemp = $_FILES['arquivo']['tmp_name'];
	// O código de erro associado a este upload de arquivo
	$arqError = $_FILES['arquivo']['error'];

	if ($arqError == 0) {
        // Verifica o tipo de arquivo enviado
		if (array_search($arqType, $tiposPermitidos) === false) {
			echo 'O tipo de arquivo enviado é inválido!';
		// Verifica o tamanho do arquivo enviado
		} else if ($arqSize > $tamanhoPermitido) {
			echo 'O tamanho do arquivo enviado é maior que o limite!';
		// Não houveram erros, move o arquivo
		} else {
			$pasta = '/uploads/';
			// Pega a extensão do arquivo enviado
			$extensao = strtolower(end(explode('.', $arqName)));
			// Define o novo nome do arquivo usando um UNIX TIMESTAMP
			$nome = time() . '.' . $extensao;

			$upload = move_uploaded_file($arqTemp, $pasta . $nome);
		}
	}

?>

Na linha 31 pegamos a extensão do arquivo enviado e na linha 33 criamos um novo nome para ele usando um UNIX TIMESTAMP e a extensão original.

6.0 – Salvando tudo no banco de dados

Acabamos de passar por todas as partes do upload e manipulação de um arquivo!

Agora vamos salvar os dados recebidos no banco de dados apenas para concluir o exemplo da criação de um perfil em uma rede social:

<?php

	// Aqui você faz a conexão com o banco de dados

	// Lista de tipos de arquivos permitidos
	$tiposPermitidos= array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png');
	// Tamanho máximo (em bytes)
	$tamanhoPermitido = 1024 * 500; // 500 Kb

	// O nome original do arquivo no computador do usuário
	$arqName = $_FILES['arquivo']['name'];
	// O tipo mime do arquivo. Um exemplo pode ser "image/gif"
	$arqType = $_FILES['arquivo']['type'];
	// O tamanho, em bytes, do arquivo
	$arqSize = $_FILES['arquivo']['size'];
	// O nome temporário do arquivo, como foi guardado no servidor
	$arqTemp = $_FILES['arquivo']['tmp_name'];
	// O código de erro associado a este upload de arquivo
	$arqError = $_FILES['arquivo']['error'];

	if ($arqError == 0) {
        // Verifica o tipo de arquivo enviado
		if (array_search($arqType, $tiposPermitidos) === false) {
			echo 'O tipo de arquivo enviado é inválido!';
		// Verifica o tamanho do arquivo enviado
		} else if ($arqSize > $tamanhoPermitido) {
			echo 'O tamanho do arquivo enviado é maior que o limite!';
		// Não houveram erros, move o arquivo
		} else {
			$pasta = '/uploads/';
			// Pega a extensão do arquivo enviado
			$extensao = strtolower(end(explode('.', $arqName)));
			// Define o novo nome do arquivo usando um UNIX TIMESTAMP
			$nome = time() . '.' . $extensao;

			// Escapa os caracteres protegidos do MySQL (para o nome do usuário)
			$nomeMySQL = mysql_real_escape_string($_POST['nome']);

			$upload = move_uploaded_file($arqTemp, $pasta . $nome);

			// Verifica se o arquivo foi movido com sucesso
			if ($upload == true) {
				// Cria uma query MySQL
				$sql = "INSERT INTO `contas` (`id`, `nome`, `foto`) VALUES (NULL, '". $nomeMySQL ."', '". $nome ."')";
				// Executa a consulta
				$query = mysql_query($sql);

				if ($query == true) {
                    echo 'Usuário inserido com sucesso!';
                }
			}
		}
	} else {
		echo 'Ocorreu algum erro com o upload, por favor tente novamente!';
	}

?>

Espero que tenham gostado e entendido! ;)

Você também vai gostar de ler:

Postado em Artigos, MySQL, PHP, Tutoriais

Com as tags , , , , , , , , , , , , , , , , , , , , ,

Escrito por Thiago Belem

Gostou desse artigo?

Não se esqueça de assinar o RSS e divulgue-o para o mundo:

  • Lispa9
    Muito bom !!!
  • Willian Cima
    Thiago, criei um sistema de upload múltiplo, mas após começar a usar criptografia md5 nos títulos, todas imagens upadas ficam iguais a primeira selecionada.

    Segue meu script:
    <?php
    include 'config.php';

    if ( !isset($_SESSION["Username"]) ) {
    header("location: loginform.php");
    exit;
    }

    if(isset($_POST['upload'])){
    $pasta = 'images_files/';
    foreach($_FILES["img"]["error"] as $key => $error){

    if($error == UPLOAD_ERR_OK){
    $tmp_name = $_FILES["img"]["tmp_name"][$key];
    $cod = date('dmy') . '-' . $_FILES["img"]["name"][$key];
    $nome = $_FILES["img"]["name"][$key];
    $uploadfile = $pasta . basename($nome);
    $Tags = $_POST[Tags];



    // Pega a extensão do arquivo enviado

    $extensao = strtolower(end(explode('.', $cod)));

    // Define o novo nome do arquivo usando um UNIX TIMESTAMP

    $nome = md5(time()) . '.' . $extensao;



    if(move_uploaded_file($tmp_name, $pasta . $nome)){

    $inserir = mysql_query("INSERT INTO images (ImageID, Cid, Sid, Title, Tags, Image, Viewed, Published, TimeStamp, Username, Email_Address) VALUES ('', '', '', '', '$Tags', '$nome', '', 'Yes', '', '$_SESSION[Username]', '$_SESSION[Email_Address]')");

    header("location:myimages.php");

    } } } } ?>

    Pode me ajudar?

    Abs.
  • Você está usando o time() e todos os uploads acontecem no mesmo segundo, resultado: MD5s iguais.

    Use uniqid() no lugar do time.
  • Willian Cima
    PQP, cara, vc é phoda!! Me salvou diversas vezes UAHUHAUHAUAHU
    Continue com este trabalho magnífico.

    Abs.
  • Parabém Thiago, ótimo artigo, não achei em nenhum lugar igual ao seu, e além de funcionar direitinho, aprendi a fazer também, Obrigado :D
  • Muito bem explicado o tutorial. Parabéns!
  • Olá Tiago tuido bom?
    Tenho um blog e gostaria de saber se eu posso fazer uma página de uplod de fotos que seriam enviadas para uma outra página tipo "galeria?
    Meu blog é no Blogspot.
    Seu blog é muito bom parabéns!
    abs.
  • @Lisete
    Provavelmente você vai conseguir essa resposta na página de ajuda do Blogger.
  • Zucolli
    Olá Thiago...

    Está dando um erro que eu não encontro solução...

    Warning: move_uploaded_file(../uploads/lista.csv) [function.move-uploaded-file]: failed to open stream: No such file or directory in C:\xampp\htdocs\UPLOAD\recebe.php on line 32

    Warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move 'C:\xampp\tmp\php662.tmp' to '../uploads/lista.csv' in C:\xampp\htdocs\UPLOAD\recebe.php on line 32

    Você pode olhar?
    Obrigado!
  • @Zucolli
    O script não conseguiu localizar o diretório onde irá salvar o arquivo, verifique se você definiu o caminho corretamente e se ele existe.
  • Esse método também pode ser adaptado para envio de arquivo tipo "*.jar" (formato Java)?

    Tem tutorial para fazer o download também, para puxar os arquivos postado na pasta "uploads"?
  • Olá Thiago...

    Em primeiro lugar parabéns pelo tutorial.
    Estou utilizando sua dica pra fazer o upload de um mp3.
    Quando dou o comando print_r() antes do if, meu vetor está retornando assim: Array() e consequentemente dá erro na comparação do MiME.
    Acontece que já olhei o name do input file e está correto. O que pode ser?

    Grato,
  • Matheus
    Vlw ae Thiago !

    to dando uma estuda aew !

    Abraço
  • Matheus
    Continua movendo só o segundo arquivo..

    e se eu inserir só o primeiro arquivo no 1 input ele da aquele erro:

    "Ocorreu algum erro com o upload, por favor tente novamente!"

    e seu inserir só o segundo, da tudo certo..

    oq pode ser??
  • @Matheus
    Dá uma estudada melhor em "estruturas de repetição", "multiplos uploads" no PHP... Eu posso ficar a tarde toda aqui tentando te explicar mas é uma coisa q vc precisa entender antes de fazer.

    Qualquer duvida é so falar... Abraços
  • Matheus
    Deu certo!!

    Inseriu os dois nomes dos arquivos no banco,
    mas só moveu o segundo arquivo pra pasta upload..

    oq pode ser??
  • @Matheus
    Talvez os dois uploads estão acontecendo muito rápido e um arquivo tá sobrescrevendo o outro...

    Tente isso na linha 34:
    $nome = $_FILES['arquivo']['name'][$n];

    Antes era assim:
    $nome = time() . '.' . $extensao;
  • Matheus
    Deu certo !!

    só tenho uma duvida agora..

    como eu posso colocar 2 arquivos diferentes
    em dois campos do banco??

    $sql = "INSERT INTO `upload` (`id`, `nome`, `foto`, `video`) VALUES (NULL, '". $nomeMySQL ."', '". $nome ."', '". $nome ."')";

    Aí quando eu insiro 2 arquivos diferentes nas inputs, ele pega o segundo e insere em foto e video o mesmo arquivo.
  • @Matheus
    Como está dentro de um LOOP você precisa montar a query fora desse loop e executá-la apenas uma vez... Dentro do LOOP você apenas define os nomes dos arquivos mas poderia ser algo assim:

    $sql = "INSERT INTO `upload` (`id`, `nome`, `foto`, `video`) VALUES (NULL, '". $nomeMySQL ."', '". $_FILES['arquivo']['name'][0] ."', '". $_FILES['arquivo']['name'][1] ."')";
  • Matheus
    Thiago
    fiz isso que voce disse e
    agora exibe o seguinte erro:

    "Ocorreu algum erro com o upload, por favor tente novamente!"

    O que eu fiz de errado?

    foreach($_FILES['arquivo'] as $arquivo){
    $arqName = $_FILES['arquivo']['name'];
    $arqType = $_FILES['arquivo']['type'];
    $arqSize = $_FILES['arquivo']['size'];
    $arqTemp = $_FILES['arquivo']['tmp_name'];
    $arqError = $_FILES['arquivo']['error'];
    }
blog comments powered by Disqus