Fala galera, tudo bem? No post de hoje veremos uma forma bem legal de colocar um simpático formulário de upload de arquivos com barra de progresso utilizando AJAX(JQuery).
Para acompanhar o post, recomendo a leitura desse post, que é onde abordo uma função php para fazer o upload de arquivos de forma segura e simples. É essa função que utilizarei no exemplo de hoje.Para começar, baixe o JQuery e o plugin JQuery.Form. Feito isso, nossa estrutura de diretórios e arquivos deverá ficar da seguinte maneira:
- index.php (Página onde vai o formulário)
- jquery.js (Plugin javascript)
- jquery.form.js (Plugin Jquery para trabalhar com formulários)
- upload.js (Define as regras da requisição assincrona)
- enviar_arquivo.php (Realiza o upload do arquivo)
- funcao_upload.php (Função para auziliar o download)
- uploads (Diretório onde os arquivos serão salvos)
Ressalto que no nosso exemplo trabalharemos apenas com upload de imagens. Mas fique à vontade para trabalhar com o upload de qualquer tipo de arquivo.
Arquivo index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <!DOCTYPE html> <html> <head> <title>www.rafaelwendel.com - Upload de arquivos com barra de progresso</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script src="jquery.js" type="text/javascript"></script> <script src="jquery.form.js" type="text/javascript"></script> <script src="upload.js" type="text/javascript"></script> </head> <body> <h1><a href="http://www.rafaelwendel.com" target="blank" rel="noopener">www.rafaelwendel.com</a> - Upload de arquivos com barra de progresso</h1> <form name="formUpload" id="formUpload" method="post"> <label>Selecione o arquivo: <input type="file" name="arquivo" id="arquivo" size="45" /></label> <br /> <progress value="0" max="100"></progress><span id="porcentagem">0%</span> <br /> <input type="button" id="btnEnviar" value="Enviar Arquivo" /> </form> <div id="resposta"> </div> </body> </html> |
No cabeçalho faço a inclusão dos 3 arquivos javascripts que serão utilizados. No corpo, insiro um formulário de nome/id “formUpload” e dentro desse formulário o campo do tipo “file” chamado “arquivo”.
Na linha 15 é onde vai a barra de progresso que inicialmente tem o valor de 0% e que será preenchida automaticamente quando o upload estiver sendo executado.
Depois vem o botão “btnEnviar” que será o responsável para submeter o formulário.
A div “resposta” será o local onde exibiremos as mensagens retornadas pelas requisições AJAX.
Agora vamos à implementação do arquivo upload.js . É nesse arquivo que definiremos as regras para a requisição assíncrona para upload do arquivo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | $(document).ready(function(){ $('#btnEnviar').click(function(){ $('#formUpload').ajaxForm({ uploadProgress: function(event, position, total, percentComplete) { $('progress').attr('value',percentComplete); $('#porcentagem').html(percentComplete+'%'); }, success: function(data) { $('progress').attr('value','100'); $('#porcentagem').html('100%'); if(data.sucesso == true){ $('#resposta').html('<img src="'+ data.msg +'" />'); } else{ $('#resposta').html(data.msg); } }, error : function(){ $('#resposta').html('Erro ao enviar requisição!!!'); }, dataType: 'json', url: 'enviar_arquivo.php', resetForm: true }).submit(); }) }) |
Definimos a ação no botão “btnEnviar”. Quando ele for clicado o “formUpload” é submetido via requisição AJAX. É aí que definimos as regras através dos parâmetros descritos à seguir:
- uploadProgess :responsável por gerenciar o progresso do upload (barra de progresso)
- sucess : o que fazer em caso de sucesso (Se tudo der certo ele exibe na div “resposta” a imagem que foi enviada)
- error : o que fazer em caso de erro (Exibe na div “resposta” uma mensagem de erro)
- dataType : o tipo de dado que será uilizado na transmissão de informações (note que utilizamos o JSON em nosso exemplo)
- url : a arquivo server-side que será executado (No caso: enviar_arquivo.php)
- resetForm : resetar o formulário ao término da execução
Agora só falta o arquivo enviar_arquivo.php que é o responsável por fazer o trabalho em si do upload do arquivo “por baixo dos panos”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php /* Importa o arquivo onde a função de upload está implementada */ require_once('funcao_upload.php'); /* Captura o arquivo selecionado */ $arquivo = $_FILES['arquivo']; /*Define os tipos de arquivos válidos (No nosso caso, só imagens)*/ $tipos = array('jpg', 'png', 'gif', 'psd', 'bmp'); /* Chama a função para enviar o arquivo */ $enviar = uploadFile($arquivo, 'uploads/', $tipos); $data['sucesso'] = false; if($enviar['erro']){ $data['msg'] = $enviar['erro']; } else{ $data['sucesso'] = true; /* Caminho do arquivo */ $data['msg'] = $enviar['caminho']; } /* Codifica a variável array $data para o formato JSON */ echo json_encode($data); |
Ele utiliza a função uploadFile que está implementada no funcao_upload.php. As informações de sucesso ou erro são armazenadas dentro de um array que no final é codificado para o formato JSON para que o javascript seja capaz de recebê-las e utilizá-las.
E ponto final. Teste o seu formulário. Se tudo ocorrer corretamente, após o término do upload a imagem será exibida na tela.
Para fazer o download dos arquivos do post, clique aqui.
Em caso de dúvidas, utilize a caixa de comentários.
Abs
Siga-me no twitter: @rafaelwendel
O arquivo e enviado mais da uma mensagem erro “Erro ao enviar requisição!!!”
É a mensagem do ajaxForm para quando algo da errado.
Verifique a url que está sendo chamada e se dentro dela tudo está acontecendo de forma correta.
Abs
Bom dia Leonardo. O problema ocorre por alguns erros no código PHP.
Faça as seguintes alterações e tudo vai funcionar corretamente:
funcao_upload.php
$nomeOriginal = $nomeOriginal . $infos[$i] . “.”; // Errado, variável $nomeOriginal não existe
$nomeOriginal = $arquivo[“name”] . $infos[$i] . “.”; // Correto
enviar_arquivo.php:
if($enviar[‘erro’]){ // Errado, pode não existir um erro
$data[‘msg’] = $enviar[‘erro’];
}
if(isset($enviar[‘erro’])){ Correto, se existir um erro mostra o erro
$data[‘msg’] = $enviar[‘erro’];
}
Com essas alterações funciona perfeitamente. Um abraço
Gostaria de saber se com esse código é viável implementar o Upload via Drag ‘n Drop.
Olá Wiliiam,
Nunca pensei nisso, mas acredito que seja possivel sim. Mas aí terás que dar uma estudada no modelo Drag And Drop. Segue sugestão:
http://jqueryui.com/draggable/
http://jqueryui.com/droppable/
Abs!
Olá, gostei muito e já estou utilizando, porém quando vou fazer o upload ele não enviar arquivos com mais de 2Mb. Sabe por que?
Olá Diego,
Esse problema acontece porque por padrão o php permite que apenas arquivos de até 2Mb sejam enviados. Mas essa configuração pode ser alterada para um valor de sua preferência. Veja um tópico que aborda esse assunto:
http://www.emersoncarvalho.com/php-aumentando-o-tamanho-maximo-de-upload/
Obrigado pela visita.
Abs!
Rafael testei os arquivos aqui mas sempre reporta o seguinte erro: já dei uma olhada nos arquivos js e php e não consegui encontrar a causa do problema;
Dei permissão total para a pasta e não adiantou;
Tem alguma extensão ou modulo do PHP e apache que deva ser liberada em especifico para funcionar as classes?
Obs.: O erro é este: “Erro ao enviar requisição!!!”
Olá Rodrigo,
Nada deve ser habilitado para que o upload funcione sem problemas.
O erro (“Erro ao enviar requisição” – Linha 19) acontece porque por algum motivo a requisição AJAX não conseguiu ser efetuada.
Possíveis causas:
– URL está incorreta.
– Nao houve um retorno no formato JSON esperado
– Algum erro na URL que esta sendo executada.
Dê uma olhada no seu código e vê se tudo está de acordo.
Abs!
Rafael eu fiz o teste com algumas alterações simples e com o script orginal baixado
no arquivo original é necessário fazer alguma alteração para que o script funcione???
Obs.: Testei o script via WAMP
Olá Rodrigo,
A unica exigência do material original é incluir o arquivo funcao_upload.php que eu abordo nesse artigo: http://www.rafaelwendel.com/2011/06/funcao-php-para-upload-de-arquivos/
Att.
cara show de bola este script, porem teria como enviar os arquivos para um banco de dados?
Olá Gabriel,
Creio que é muito mais fácil salvar o arquivo normalmente em uma pasta de seu servidor e inserir apenas o caminho (link) dele em um banco de dados do que salvar o próprio arquivo em um banco de dados.
Abs!
como faço para exibir o link para download do arquivo após o upload como no 4shared?
Cícero, basta alterar a linha 12 do código JQuery para:
Abs!
nao entendi como fazer essa parte :/
Parabéns pelo POST!
Me ajudou muitooooo.
Realizei algumas alterações nos arquivos disponibilizados aqui, onde consertei o erro que mesmo que envie a imagem, informava erro ou de json etc…
O .arj contem os arquivos fornecidos aqui, mas com correções e funcional.
Para acessar, segue link abaixo:
http://www.sendspace.com/file/tl68gq
Abraços!
Realizado um ajusto na barra de progresso.
Favor Ignorar o link acima e baixar por:
http://www.sendspace.com/file/57hvm5
Parabéns pelo Post!
ICR.
Obrigado pela contribuição Ivan.
Abs!
Ivan pode me enviar os arquivos corrigidos ? O Link que vc postou expirou amigo, preciso muito pode me ajudar abraço!
Bom Dia!
Gostaria de saber, como posso fazer para ao selecionar o arquivo, já fazer o upload!
Obrigado
Você diz sem precisar clicar no botão “Enviar Arquivo” ?
mt bom o post me ajudou mt,mas…
como colocar um botao de cancelar o upload?
Como fazer para aumentar o tamanho dos arquivos que serão upados?
to precisando colocar para upar arquivos de no minimo 30 MB
Olá Hugo,
Como já havia indicado alguns comentarios acima, segue otimo tutorial para aumentar o limite de tamanho dos arquivos
http://www.emersoncarvalho.com/php-aumentando-o-tamanho-maximo-de-upload/
Abs!
Nao funciona com arquivos .mp3?
Ola ALain,
Funciona com qualquer tipo de arquivo. Basta adicionar a extensão na linha 8 do enviar_arquivo.php
Abs
Rafa, eu tentei de tds as formas. na index.php, no enviar_arquivo.php, no funcao_upload.php.
Só nao tentei no tal php .ini pq nao sei aonde é isso…
Não tem como vc nos ensinar da mesma maneira que fez aqui nessa página?
Fazer um tutorial bem detalhado.
Não digo entregar os arquivos de mão beijada, apenas mostrar como se faz.
Estou entrando nesta área agora , e ja cheguei na pagina 60 do google e não consegui achar a maneira correta de se fazer esses arquivos grandes subirem.
Hoje eu vejo a falta que faz um professor rsrsrsrs
Desde já meu muito Obrigado.
UP!!
Rafael,
Boa solução. Essa solução tem algum copyright?
Dependendo, tu poderias disponibilizar no github.
Abração!
Faço até questão de comentar cara.
Perfeito…
Quase 1 mês da minha ultima questão…
Tem como dar um Help???
Hugo, se o arquivo for maior que 2M é necessário alterar algumas configurações do php.
Veja esse artigo
http://www.emersoncarvalho.com/php-aumentando-o-tamanho-maximo-de-upload/
Abs
Aew rafael blz?
É seguinte estou tendo problemas com o servidor local e o da minha hospedagem.
No local ocorre tudo bem, mas no da minha hospedagem ocorre o seguinte erro: Erro ao enviar requisição.
Qual será o motivo?
Será que a hospedagem nao da surporte a JSON, ou Jquery?
Abraço e parabens pelo blog.
Olá Jonatas.
O javascript é rodado do lado cliente e não servidor, logo não pode ser problema de suporte da hospedagem.
Para tentar descobrir o erro, altere a linha 19 (de acordo com meu exemplo) do arquivo upload.js para:
Isso fará ele “imprimir” a mensagem de erro. Verifique a mensagem e tente pesquisar soluções ou poste ela aqui.
Abs!
Aew rafeal blz?
Adicionei tambem o código que você pediu, mas ele nao imprimiu nenhuma mensagem:
Então fui no console e apareceu isso, olha ai imagem:
http://www.brimages.com.br/images/894erro_upload_de_imagem.png
Altere a linha 18 de:
para:
Veja o erro
Abs
Aew rafel deu consegui imprimir o erro.
Olha ai a mensagem que deu, eu tirei um print, olhai ai.
http://www.brimages.com.br/images/976erro_teresina_rindes.png
Abraçoo,, quem souber o problema por favor ajudem-me!!
Opa,
Alguém está com problema no IE9 ? , ele faz o Upload mas sem barra de progresso.
FF e Chrome vai bem.
Ps: Parabéns pelo Artigo
Jaguer
Rafael, estou ficando louco já… rsrs…
Aqui está dando erro de:
– Uncaught TypeError: Object [object Object] has no method ‘ajaxForm’.
Não sei mais onde mexer pra que funcione. Já comparei umas 300 vezes o seu arquivo com o meu e nada…
Abraços…
Esqueci de postar o meu código…
$(document).ready(function(){
$(‘#btnEnviar’).click(function(){
var arquivo = $(‘#arquivo’).val();
extensoes_permitidas = new Array(“.zip”, “.rar”, “.pdf”);
if (!arquivo) {
$.post(“dlf.php”, {act: “ai”}, function(data) {
$(“#lightbox-msg, #lightbox-panel-msg”).fadeIn(300);
$(‘#lightbox-panel-msg’).load(“carq.php?v=”+data);
});
$(‘#barrafundo’).hide();
}else{
extensao = (arquivo.substring(arquivo.lastIndexOf(“.”))).toLowerCase();
permitida = false;
for (var i = 0; i < extensoes_permitidas.length; i++) {
if (extensoes_permitidas[i] == extensao) {
permitida = true;
break;
}
}
if (!permitida) {
$.post("dlf.php", {act: "ae"}, function(data) {
$("#lightbox-msg, #lightbox-panel-msg").fadeIn(300);
$('#lightbox-panel-msg').load("carq.php?v="+data);
});
$('#barrafundo').hide();
}else{
var barra = $('#barra');
$('#barrafundo').show();
$('#formUpload').ajaxForm({
uploadProgress: function(event, position, total, percentComplete) {
barra.width(percentComplete*5);
$('#porcentagem').html(percentComplete+'%');
},
success: function(data) {
barra.width(500);
$('#porcentagem').html('100%');
if(data.sucesso == true){
$.post("dlf.php", {act: "ao"}, function(data) {
$("#lightbox-msg, #lightbox-panel-msg").fadeIn(300);
$('#lightbox-panel-msg').load("carq.php?v="+data);
});
}else{
var resp = data.msg;
$.post("dlf.php", {act: ""+resp+""}, function(data) {
$("#lightbox-msg, #lightbox-panel-msg").fadeIn(300);
$('#lightbox-panel-msg').load("carq.php?v="+data);
});
$('#barrafundo').hide();
}
},
error : function(){
var respp = data.msg;
$.post("dlf.php", {act: ""+respp+""}, function(data) {
$("#lightbox-msg, #lightbox-panel-msg").fadeIn(300);
$('#lightbox-panel-msg').load("carq.php?v="+data);
});
},
dataType: 'json',
url: 'enviararquivo.php',
resetForm: true
}).submit();
}
}
});
});
Muito bom, funcionou perfeitamente parabéns!
Muito bom o tutorial, facil de ententer!!!
Mas estou com um problema: nao esta sendo enviado corretamente o campo file pelo ajax.
O php me deu a seguinte mensagem: “Notice: Undefined index: arquivo in C:\wamp\www\aptana\UPLOAD\enviar_arquivo.php on line 6″
Entao adicionei essa linha:
var_dump($_FILES);
antes da linha:
$arquivo = $_FILES[‘arquivo’];
e deu como resultado:
array
empty
Tentei mudar o enctype do formulario, mas nao mudou nada.
Coloquei também essa linha:
var_dump($_POST);
e deu o resultado:
array
‘arquivo’ => string ” (length=0)
Alguem sabe como resolver este problema??? xD
Olá Oeslei,
Confira o nome e o tipo do campo no formulário. Pelo que você colocou parece que o campo está como text e nao como file.
Abs!
É possível personalizar o elemento ?
Olá João,
É possível sim. É só aplicar css ao elementos progress e #porcentagem
Abs!
Olá Rafael, também utilizo este script para upload de arquivos e estou tendo um problema.
Ao testar o script localmente tudo funciona perfeitamente, mas ao testar no servidor e tentar enviar um arquivo com algum caracter especial no nome (exemplo: [name’sfile.jpg]) é retornado um erro de requisição (no caso no teste que fiz com seus arquivos, no meu caso retorna SyntaxError: JSON.parse: unexpected character), mas acredito que o erro seja o mesmo.
Você sabe como validar esse envio de dados para solucionar o problema? Já estou tentando a algum tempo e pelos testes que venho fazendo o problema parece nem chegar no arquivo php, parece estar no próprio script do jQuery.Form. Já fez esse teste?
Obrigado e fico no aguardo…
Abraços.
Cara,
Dê uma olhada nesse post e vê se pode te ajudar
http://www.rafaelwendel.com/2011/06/resolvendo-problemas-com-acentuacao-no-php/
Abs!
Bom dia Rafael
Estou com problema onde o arquivo é enviado, mas a barra de progresso não anda, e o retorno do arquivo não carrega, mas se eu clicar sem selecionar arquivo o erro vem, se eu colocar alguma extensão não permitida ele tambem não dar retorno, alguma ideia do que seria?
e parabens pelo post.
Geraldo
Boa tarde,
Parabéns, ótimo código!
Consigo alterar o caminho do upload do arquivo para outro servidor, que não seja o web e sim um servidor de arquivos.
Grato
Olá Thiago,
Não entendi muito bem o que você quis dizer.
Abs!
Boa tarde Rafael,
Na linha 12 do arquivo ‘enviar_arquivo.php’, o segundo parâmetro é o diretório para onde realizamos o upload, eu poderia colocar um servidor da rede neste parâmetro. Por exemplo:
$enviar = uploadFile($arquivo, ‘\\meuservidor\public\uploads/’, $tipos);
Explicando melhor, o servidor web para onde realizo os uploads tem pouco espaço em disco, mas tem um servidor de arquivos que seria exatamente para receber estes arquivos.
Ou se conseguir pensar em alguma outra solução e me dar uma dica.
A linha 12 do arquivo é essa:
/* Chama a função para enviar o arquivo */
$enviar = uploadFile($arquivo, ‘uploads/’, $tipos);
Valeu!
Ah sim, entendi.
Então, nunca tinha pensado nisso, mas acredito que se a app tiver acesso à esse local na rede funcionará sem problemas.
Abs
Rafael, blz…
Muito bom este seu script….
Vc poderia me ajudar somente com uma coisa…?
preciso que seja enviado também uma frase que faz ser digitada em uma caixa de texto…
Conseguir achar a solução…
valeu
Olá!
Estou tentando criar um botão de upload de arquivos que envie documentos do Word, Excel, PDF diretamente do meu site.
É para receber orçamentos e cotações.
Gostaria de criar numa linguagem simples, HTML de preferência, pois não sei usar PHP.
Um Form que faça upload de pelo menos 3 arquivos
Preciso que o site envie os documentos diretamente para meu e-mail.
Não há necessidade de campos nome, assunto, etc!
Poderia me ajudar?
Olá Fernando,
Dê uma olhada nesse post, acho que irá te ajudar. Ele não exige tantos conhecimentos em php para ser implementado.
http://www.rafaelwendel.com/2011/06/emails-com-anexo-utilizando-a-classe-phpmailer/
Abs!
Rafael, simplesmente perfeito.
Estava tentando com o uploadfy e até deu certo, mas pra customizar os erros eu estava apanhando d+, até encontrar seu post com esta outra abordagem… Muito obrigado cara, sou seu fã… forte abraço…
Blz fera..
Gostaria de tirar uma duvida em relação ao meu código..
ao enviar a imagem, está enviando duas de cada vez. o que sera?
no aguardo..
ate+
Olá Luyrton,
Você definiu o seu botão como sendo do tipo “submit” ou “button” ???
Abs!
Olá amigo parabéns pelo post gostaria de saber se têm como acrescentar vários inputs para enviar mais de 1 anexo e se tiver como além de enviar para a pasta de uploads se têm como enviar tbm para o email de destino ?
Ótimo código. Só não tenho conseguido um exemplo para múltiplos arquivos…
Parabéns !! Bacana demais
Gostaria que fize- se o envio de 8 arquivos selecionados – multiplos arquivos. – me ajude !!! Urgente!!
Obrigada!!
Boa tarde, tudo bem, primeiramente gostaria de parabenizá-lo pelo seu trabalho, tem ajudado muitos desenvolvedores iniciantes a não se tornarem script kiddies, ou moleques de script, enfim, eu estou com uma dúvida e não consegui resposta pelos meios convencionais, você sabe se tem algum meio de colocar no meu site um botão de upload que façam os arquivos irem para o 4shared ou algum outro serviço de Cloud Hosting disponível na internet ?°
Att,
Luciano dii Souza WD.
+ 55 31 9831-3692
Olá Luciano,
Isso aí depende se o provedor oferece o serviço. Dando uma rápida pesquisada aqui vejo que o 4shared oferece uma API para que desenvolvedores conectem suas aplicações e utilizem os serviços do site. Porém, para implementar você precisará de conhecimentos pelo menos intermediários em PHP ou outra linguagem.
Bom, segue link (em inglês) para você dar uma olhada: http://help.4shared.com/index.php/SOAP_API
Boa sorte.
Abs!
Boa tarde, Cara muito bom esse tutorial, parabéns e obrigado pelas dicas de ouro!
Gostaria de saber se tem como adaptar esse script para fazer upload de vários arquivos, tipo quando clicar para procurar o arquivo poder selecionar vários arquivos?
Obrigado!
Sei que o post é meio antigo mas não custa perguntar… preciso salvar o nome do arquivo “upado” e algumas outras informações sobre o arquivo no banco de dados. Minha dúvida é, onde executo o script myql para inclusão no banco de dados?
Enoque,
No arquivo enviar_arquivo.php, dentro do else que se inicia na linha 19 (condição caso o upload tenha sido feito com sucesso), você pode se conectar com o banco e fazer a inserção.
Abs!
Valeu, obrigado.
Olá, amigo! Parabéns pelo artigo, muito bom!
Só um dúvida… estou com o mesmo problema de alguns acima, da linha 19 do arquivo ‘upload.js’. Ele apresenta o erro “Erro ao enviar requisição!!!” ao término do upload, porém o arquivo é salvo normalmente na pasta nomeada.
O que pode estar ocasionando este erro?
Acrescentei a função para mostrar o erro na tela, e me retornou isso: http://i.snag.gy/iKjNg.jpg
Agradeço desde já!
Abraço
Olá Thiago,
Esse “Notice” na verdade não é necessariamente um erro. Ela apareceu não porque deu algum erro no script mas porque você tentou usar uma variável que não existe (nomeOriginal) e acessar uma posição inexistente no array (erro). Como esse notice é disparado, o AJAX entende que o arquivo .php não foi executado direito. Você pode desabilitar o aparecimento desse tipo de mensagem (os notices). Dê uma olhada em http://forum.imasters.com.br/topic/470546-ocultar-notice-php/
Ou se preferir pode refatorar o seu código verificando as variáveis e arrays.
Abs!
falae rafael, bom dia.
cara, preciso implementar um retorno de pagina, o que seria mais interessante, no jquery ou no php?
outra duvida, se fosse um upload tipo do instagram, ele começa o upload no retorno da pagina. daria para fazer com este form?
abraço
elio
Muito obrigado Rafael, me foi de muita ajuda! Demorei um dia inteiro para descobrir que eu estava usando uma variável $data no meu código, por isso dava erro no Json, mudei o nome para $datax e tudo funcionou perfeitamente!
Como faço para enviar para o email e não armazenar em pastas?
Olá Jorge.
Dê uma olhada nesse post: http://www.rafaelwendel.com/2011/06/emails-com-anexo-utilizando-a-classe-phpmailer/
Abs!