Nessa aula aprenderemos como criar um formulário de upload de arquivos e processar arquivos enviados com segurança em PHP. Veremos como criar um formulário e como receber o arquivos usando PHP.
Criando o Formulário HTML para Upload de Arquivos
A primeira coisa que temos que fazer é criar o formulário conforme vimos na aula passada. Mas o <form> tem que conter o atributo enctype com o valor multipart/form-data. Caso contrário, o navegador não poderá fazer upload de arquivos.
#1 Dentro do arquivo index.php digite(veja o enctype=”multipart/form-data”):
<html> <body> <form action="index.php" method="POST" enctype="multipart/form-data" > </form> </body> </html>
#2 agora adicione um input do tipo file(type=”file”) e um outro input para botão de envio(submit)
<html> <body> <form action="index.php" method="POST" enctype="multipart/form-data" > <input type="file" name="arquivo"> <input type="submit" value="Enviar"> </form> </body> </html>
Demos o nome(name) de “arquivo” para nosso input type=file. Preste atenção, pois usaremos esse nome a seguir, em nosso PHP.
Esse é o nosso resultado até aqui:
Se quiser ativar a seleção de múltiplos arquivos pode usar o atributo multiple:
<input type="file" name="arquivos[]" multiple>
Note que no nome do arquivo contém colchetes [ ] quando o envio múltiplo de arquivos está habilitado.
Usando PHP para Manipular o upload de arquivos
Agora o PHP entra em jogo! Para acessar as informações do arquivo enviado usamos o array $_FILES.
O array $_FILES recebe dois parâmetros: o nome do nosso input file que é arquivo e tmp_name que é o nome do arquivo recebido. Sim, o arquivo recebido fica em uma pasta temporária e recebe um nome aleatório.
Se digitarmos a linha abaixo já veremos qual o nome e caminho do arquivo recebido.
echo $_FILES['arquivo']['tmp_file'];
Mas não digite o comando acima ainda. Iremos usar a função move_uploaded_file() para tirarmos o arquivo recebido da pasta temporária e colocarmos em uma outra que desejarmos.
A função move_uploaded_file() recebe dois parâmetros: o arquivo temporário e a pasta destino, onde ele ficará. Então, agora sim, podemos digitar nosso código para receber o arquivo:
<html> <body> <form action="index.php" method="POST" enctype="multipart/form-data" > <input type="file" name="arquivo"> <input type="submit" value="Enviar"> </form> </body> <?php move_uploaded_file($_FILES['arquivo']['tmp_name'], "documentos/recibo.txt"); ?> </html>
Acima, os arquivos serão enviados para pasta “documentos/” e o arquivo receberá o nome de “recibo.txt”.
Faça um teste e, simplesmente, o arquivo será enviado do seu pc para o seu servidorzinho web.
No lugar de tpm_name podemos ter também:
- name: nome do arquivo, exemplo $_FILES[‘arquivo’][‘name’]
- size: é o tamanho do arquivo carregado em bytes, exemplo $_FILES[‘arquivo’][‘size’]
- type: é o tipo MIME do arquivo de upload, por exemplo, imagem/jpeg para imagem JPEG ou application/pdf para arquivo PDF, , exemplo $_FILES[‘arquivo’][‘type’]
- tmp_name: é o arquivo temporário no servidor que armazenou o nome do arquivo carregado. Se o arquivo carregado for muito grande, o tmp_name será “none“, exemplo $_FILES[‘arquivo’][‘tmp_name’]
- error: é o código de erro descrevendo o status do upload, por exemplo, UPLOAD_ERR_OK significa que o arquivo foi carregado com sucesso, , exemplo $_FILES[‘arquivo’][‘error’]
Problemas e Melhorias
Está prontinho nosso sistema, mas tem alguns pontos a serem observados:
- Qualquer arquivo enviado do nosso pc pra o servidor terá o nome de recibo.txt. Por exemplo, se enviar o arquivo imagem.jpg ele ficará será o recibo.txt.
- O formulário aceita qualquer tipo de arquivo; um hacker poderá enviar um arquivo malicioso.
- O formulário não está sanitizado e nem validado. Veja: PHP – Aula 33: Validação e Sanitização de Formulário
- Um outro problema é o reenvio ao atualizarmos o navegador. Se teclarmos f5 3 vezes então o mesmo arquivo será enviado 3 vezes.
Aqui iremos tratar o primeiro e segundo problema, já que o terceiro está descrito no link.
Quanto ao quarto problema não iremos abordar nesse momento uma solução. Mas como dica, você poderá tratá-lo usando métodos de validação com if/else, isset(), $_SESSION[]…..
ACEITAR APENAS CERTOS TIPOS DE ARQUIVOS EM PHP
Para permitir que somente determinados tipos de arquivo sejam enviados, usamos o atributo accept.
<input type="file" name="arquivo" accept=".txt, .pdf" >
Acima usamos a extensão para dizer qual tipo permitir, mas podemos ter outros valores, como:
- Conforme acima, uma extensão de nome de arquivo que não diferencia maiúsculas de minúsculas, por exemplo, .jpg, .pdf, .txt
- Uma string de tipo MIME válida
- Ou uma string como image/* (qualquer arquivo de imagem), video/* (qualquer arquivo de vídeo), audio/* (qualquer arquivo de áudio). ou image/png e image/jpeg.
RESOLVENDO O PROBLEMA DO NOME DO ARQUIVO
Aqui temos diversas alternativas. Podemos,
- inserir o mesmo nome do arquivo original
- gerar um nome único, veja: PHP: Usando a Função uniqid()
Para usar o mesmo nome do arquivo original usamos: $_FILES[‘arquivo’][‘name’]
Nosso código php ficará assim:
<?php echo $nome = $_FILES['arquivo']['name']; move_uploaded_file($_FILES['arquivo']['tmp_name'], "documentos/$nome"); ?>
Para usar um nome único e aleatório usamos:
<?php //pega o nome original do arquivo echo $nome = $_FILES['arquivo']['name']; echo "<br>"; //pega os 4 ultimos caracteres, ou seja, a extensao do arquivo echo $novo_nome = uniqid("recebido") . substr($nome, -4); echo "<br>"; //move para a pasta de destino com o novo nome move_uploaded_file($_FILES['arquivo']['tmp_name'], "documentos/$novo_nome"); ?>
Configuração para Envio de Arquivos no php.ini
O PHP tem algumas opções importantes que controlam o upload do arquivo. Essas opções estão no arquivo php.ini.
Se estiver usando o xampp no Windows possivelmente seu php.ini estará em C:\xampp\php\php.ini
No Linux poderá está em /etc/php/7.4/apache2/php.ini – substitua 7.4 pela versão do seu PHP.
Temos um artigo falando sobre a localização do php.ini: Onde está o php.ini?
Também podemos usar a função php_ini_loaded_file() para vermos a localização do arrquivo php.ini
Abaixo estão as opções importantes que encontramos dentro do php.ini referentes a envio(upload) de arquivos:
; habilita uploads de arquivos HTTP.
file_uploads=On
; Diretório temporário para arquivos HTTP carregados (usará o padrão do sistema se não ; Especificadas).
upload_tmp_dir=”C:\xampp\tmp”
; Tamanho máximo permitido para arquivos enviados.
upload_max_filesize=2M
; Número máximo de arquivos que podem ser enviados por meio de uma única solicitação
max_file_uploads=20
Conclusão
Aqui aprendemos a como enviar um arquivo do pc do cliente para o servidor web.
Temos um artigo que descreve o processo de upload de um modo mais detalhado, veja:
PHP: Trabalhando com Envio(upload) de arquivos
Também temos um outro artigo que mostra como exibir pasta e arquivos: