Upload Assíncrono (iframe como AJAX) - 1 função simples

Postado por Micox - Náiron J. C. G..

12 Março, 2007

Olá povo, conforme prometido, tô postando aqui uma função pra você fazer upload bem parecido com ajax (não é ajax!!). Função simples e fácil de usar.
Ela faz um upload assíncrono, ou seja, não recarrega a página toda (assim como o AJAX).
Quem usa alguns serviços do google como o GMail ou o GooglePages já conhece este recurso muito bem.

Editado 14/01/09: Já há uma nova versão disponível.
Veja em webly.com.br/Micox/micoxUpload2.htm (ainda não está muito bem testada).
Veja os exemplos de uso em webly.com.br/Micox/micoxUpload2.htm

Upload usando apenas AJAX não é viável no ambiente da Internet pois, por motivos de segurança, os navegadores por padrão não dão acesso ao sistema de arquivos para o JavaScript (se quiser descobrir como ativar esta característica não padrão, leia aqui, mas acredito não ser muito útil ajax upload dessa forma).

Esta minha função utiliza técnicas que envolvem iframes, mas não vou dar explicações aqui não. Explicações sobre como desenvolvi a função serão dadas em um novo post. Este post aqui é só para o código.

Ah, sim, no próximo post mostrarei também uma função um pouco mais customizável já pra quem entende melhor de JavaScript.

Testado no Firefox 2.0, Internet Explorer 6.0 e Opera 9.1. Pelamordedeus, quem puder testar em outros navegadores aí e quiser citar a experiência, faça este favor à humanidade e cite a experiência nos comentários. Obrigado.

1) Coloque o código abaixo em um arquivo chamado micoxUpload.js

/* funçõezinhas padrão pra facilitar */
function $m(quem){
 //apelido só pra não ficar repetindo o document.getElementById
 return document.getElementById(quem)
}
function remove(quem){
 quem.parentNode.removeChild(quem);
}
function addEvent(obj, evType, fn){
 //o velho do elcio.com.br/crossbrowser
    if (obj.addEventListener)
        obj.addEventListener(evType, fn, true)
    if (obj.attachEvent)
        obj.attachEvent("on"+evType, fn)
}
function removeEvent( obj, type, fn ) {
  if ( obj.detachEvent ) {
    obj.detachEvent( 'on'+type, fn );
  } else {
    obj.removeEventListener( type, fn, false ); }
} 
/* a que faz o serviço pesado */
function micoxUpload(form,url_action,id_elemento_retorno,html_exibe_carregando,html_erro_http){
/******
* micoxUpload - Submete um form para um iframe oculto e pega o resultado. Consequentemente pode
*               ser usado pra fazer upload de arquivos de forma assíncrona.
* Use a vontade mas coloque meu nome nos créditos. Licença Creative Commons.
* Versão: 1.0 - 03/03/2007 - Testado no FF2.0 IE6.0 e OP9.1
* Autor: Micox - Náiron JCG - elmicox.blogspot.com - micoxjcg@yahoo.com.br
* Parametros:
* form - o form a ser submetido ou seu ID
* url_action - url pra onde deve ser submetido o form
* id_elemento_retorno - id do elemento que irá receber a informação de retorno
* html_exibe_carregando - Texto (ou imagem) que será exibido enquanto se carrega o upload
* html_erro_http - texto (ou imagem) que será exibido se der erro HTTP.
*******/

 //testando se passou o ID ou o objeto mesmo
 form = typeof(form)=="string"?$m(form):form;
 
 var erro="";
 if(form==null || typeof(form)=="undefined"){ erro += "O form passado no 1o parâmetro não existe na página.\n";}
 else if(form.nodeName!="FORM"){ erro += "O form passado no 1o parâmetro da função não é um form.\n";}
 if($m(id_elemento_retorno)==null){ erro += "O elemento passado no 3o parâmetro não existe na página.\n";}
 if(erro.length>0) {
  alert("Erro ao chamar a função micoxUpload:\n" + erro);
  return;
 }

 //criando o iframe
 var iframe = document.createElement("iframe");
 iframe.setAttribute("id","micox-temp");
 iframe.setAttribute("name","micox-temp");
 iframe.setAttribute("width","0");
 iframe.setAttribute("height","0");
 iframe.setAttribute("border","0");
 iframe.setAttribute("style","width: 0; height: 0; border: none;");
 /* Não usei display:none pra esconder o iframe
    pois tem uma lenda que diz que o NS6 ignora
    iframes que tenham o display:none */
 
 //adicionando ao documento
 form.parentNode.appendChild(iframe);
 window.frames['micox-temp'].name="micox-temp"; //ie sucks
 
 //adicionando o evento ao carregar
 var carregou = function() { 
   removeEvent( $m('micox-temp'),"load", carregou);
   var cross = "javascript: ";
   cross += "window.parent.$m('" + id_elemento_retorno + "').innerHTML = document.body.innerHTML; void(0); ";
   
   $m(id_elemento_retorno).innerHTML = html_erro_http;
   $m('micox-temp').src = cross;
   //deleta o iframe
   setTimeout(function(){ remove($m('micox-temp'))}, 250);
  }
 addEvent( $m('micox-temp'),"load", carregou)
 
 //setando propriedades do form
 form.setAttribute("target","micox-temp");
 form.setAttribute("action",url_action);
 form.setAttribute("method","post");
 form.setAttribute("enctype","multipart/form-data");
 form.setAttribute("encoding","multipart/form-data");
 //submetendo
 form.submit();
 
 //se for pra exibir alguma imagem ou texto enquanto carrega
 if(html_exibe_carregando.length > 0){
  $m(id_elemento_retorno ).innerHTML = html_exibe_carregando;
 }
 
}

2) Inclua (chame) este arquivo no seu HTML

<script type="text/javascript" src="micoxUpload.js"></script>

3) Os parâmetros na hora de chamar a função são:

  1. form - o form a ser submetido ou o ID de algum form que queira submeter.
  2. url_action - url pra onde deve ser submetido o form. Tem a mesma função do parâmetro "action" de um form.
  3. id_elemento_retorno - id do elemento que irá receber a informação de retorno.
  4. html_exibe_carregando - Texto (ou imagem) que será exibido enquanto se carrega o upload
  5. html_erro_http - Texto (ou imagem) que será exibido se der erro HTTP.

4) Pronto. Agora você várias formas de ativar o upload assíncrono. Vou exemplificar aqui 3 formas dentre as várias possíveis:

4.1) Uso básico. Você chama o upload a partir de um button (ou um input-type-button) em um form qualquer:

<legend>Uso b&aacute;sico</legend>
  <form>
    <input type="file" name="nome_qualquer" />
    <div id="recebe_up_basico" class="recebe">&nbsp;</div>
    <button onClick="micoxUpload(this.form,'upa.php','recebe_up_basico','Carregando...','Erro ao carregar'); return false;" type="button">testa</button>
  </form>
</fieldset>

4.2) Ativando o upload quando o campo file perde o foco (onblur):

<fieldset>
<legend>Uso no blur do input</legend>
  <form>
    <input type="file" name="nome_qualquer" onblur="micoxUpload(this.form,'upa.php','recebe_up_onblur','Carregando...','Erro ao carregar')" />
    <div id="recebe_up_onblur" class="recebe">&nbsp;</div>
  </form>
</fieldset>

4.3) Agora uma forma que deixará seu form/upload acessível mesmo que o javascript esteja desabilitado:

<fieldset>
<legend>Uso não intrusivo</legend>
    <form action="upa.php" target="_blank">
    <input type="file" name="nome_qualquer" onblur="micoxUpload(this.form,'upa.php','recebe_up_3','Carregando...','Erro ao carregar')" />
    <div id="recebe_up_3" class="recebe">&nbsp;</div>
  </form>
</fieldset>

Pronto. Customize aí agora e bora "uploadar". Bugs, erros, comenta ae.
Por favor, DÚVIDAS SOMENTE NO FÓRUM !!

No próximo post, a explicação e uma versão mais customizável pra quem já entende de JavaScript.

Marcadores: ,

E-mail Newsletter Feed RSS Resultado! Concursos Shopping Resultado

Não mande dúvidas nos comentários ou no meu e-mail. Mande elas para o fórum de desenvolvedores Webly. Tem mais gente lá gabaritada a responder e você não fica dependendo só do mico.


Comenta aí! Não cai o dedo e me incentiva a escrever mais. (47 comentários)





47 Comentários:

Blogger  disse... 12 Março, 2007 20:26  
Uhum pelo código Micox, vai me ser muito útil. veleu
Blogger Venilton disse... 13 Março, 2007 10:20  
Demais!!
Vou testar e falo como funcionou.
Será que era só eu que tava louco por isso?
Obrigado.
Blogger Lucas disse... 13 Março, 2007 17:34  
Cara... valew!!! (apesar de eu não ter entendido algumas partes.. hehe)
http://forum.ievolution.com.br/index.php?showtopic=9372
dah 1 olhada lah... ok?
Blogger JulioGreff disse... 13 Março, 2007 18:08  
Opa, vamos testar. Belo trabalho.
Blogger Micox - Náiron J. C. G. disse... 14 Março, 2007 07:13  
Opa, beleza galera.
No próximo post a explicação pra que vocês possam adaptar melhor.

E não se esqueçam de testar em diversos navegadores e me informar aqui, ok?
Blogger robson disse... 14 Março, 2007 09:56  
Muito bom esse código mas estou com um problema está dando um erro de objeto esperado, provavelmente na linha do input.
Blogger Cau disse... 17 Março, 2007 18:17  
Fala Micox, muito bom. O assunto é atualíssimo.
Cara, me interessou o seu exemplo 3 - preocupado com acessibilidade, mas... precisaríamos de um botão submit, para ser acessível... não? sem JS e sem submit, resta apenas o [ENTER], que é desconhecido da maioria.
Que tal algo assim (só tem submit se não houver JS):
criamos o botão submit com o id "sbmt", normal, visível. Então...

window.onload = function() {
$m('sbmt').style.display = 'none';
}

Abraço, Cau
Blogger Micox - Náiron J. C. G. disse... 17 Março, 2007 18:49  
É verdade Cau.
Eu lembrei só do acessível para o JavaScript e esqueci do outro tipo de acessibilidade. VAleus.
Blogger Pedro disse... 20 Março, 2007 08:20  
PARABENS BIXO
Por favor da pra tu pasar o teu msn pra mim usa o email pra mandar pedroafsouza@gmail.com
Blogger Micox - Náiron J. C. G. disse... 20 Março, 2007 08:58  
Email enviado pedro.
Blogger Ghean disse... 19 Abril, 2007 13:00  
Parabéns pelo código Micox.
Me vai ser muito util em cadastro de fotos de um sistema de concessionaria que estava parado justamente pq não conceguia um sistema de upload leval e funcional.

Seguem com seus direitos, nada de remove-los, certo?

Um grande abraço
Blogger Otavio Macedo disse... 20 Abril, 2007 09:11  
Só uma dúvida: como é que o PHP deve tratar o dado recebido? Eu fiz o seguinte teste: submeti uma imagem jpeg para o script abaixo:

header("Content-type: image/jpeg");
echo ($HTTP_RAW_POST_DATA);

O que ele retornou foi simplesmente a própria URL.
Blogger Micox - Náiron J. C. G. disse... 20 Abril, 2007 15:40  
O PHP vai trabalhar exatamente do mesmo jeito que um upload normal.
Afinal, é isto mesmo que eu faço: só faço um upload via iframe.

Eu, por exemplo, uso um script de upload básico normal que se acha aí pela net.
Anonymous Marcelo Carlos dos Santos disse... 11 Maio, 2007 14:08  
Simplesmente excelente! Esta era uma solução que eu estava buscando há muito tempo e o autor expôs de forma simplificada. É ótimo saber que existem pessoas que não têm medo de compartilhar o conhecimento. Este tipo de iniciativa é sempre bem vinda.
Parabéns e Obrigado!
Anonymous Anônimo disse... 11 Maio, 2007 23:21  
Esse script é totalmente ÚTIL!
Perfeito..
Estou terminando um pequeno sistema para os alunos postarem notas de aula via web, assim que terminar te envio o Código Fonte .. e é claro vou por seus créditos nele.. Acredito em Software Livre!
Grande abraço.
Blogger Renato disse... 19 Maio, 2007 23:09  
Tem como disponibilizar o arquivo upa.php ?? Gostaria de testar..

Outra pergunta tem como validar por exemplo somente para fazer upload de imagens (jpg e gif) ?

Renato
Blogger Micox - Náiron J. C. G. disse... 20 Maio, 2007 09:11  
Renato, é um script de upload como outro qualquer, pode ser PHP, ASP ou qualquer linguagem server-side.

Eu por exemplo, no arquivo upa.php uso este script aqui: http://www.plugmasters.com.br/sys/materias/493/1/Upload-de-Imagens-Com-Seguran%E7a
Anonymous Otata disse... 20 Junho, 2007 09:48  
Meu...show!!
Blogger Elbrinner disse... 26 Julho, 2007 12:45  
Muito bom, parabéns.
Blogger JGoulart disse... 22 Agosto, 2007 15:47  
Excelente trabalho. Sua dica funionou muito bem para mim.
Blogger eLiTe|Kym disse... 13 Outubro, 2007 02:02  
usei hoje no meu site, muito bom parabens
Anonymous Anônimo disse... 21 Novembro, 2007 09:57  
legal, mas não haveria necessidade de um javascript desse tamanho, poderia ser beeeeeeeeeem mais simples...
Blogger Micox - Náiron J. C. G. disse... 21 Novembro, 2007 13:13  
É, to sabendo manezei. Mas já tem uma versão 2.0 prontinha aqui na minha máquina só esperando eu blogar. hehe

É que tô querendo fazer uns exemplos mais reais e mais fáceis de usar.

Valeus...
Anonymous Stevão Tartari disse... 23 Dezembro, 2007 14:57  
Cara ..... você é um NINJA !!!
Parabéns ... função utilíssima
Blogger Rubiz disse... 10 Janeiro, 2008 12:06  
Para ficar ultra completo só faltava o arquivo php :o)
Blogger Rui disse... 15 Janeiro, 2008 12:49  
Bem,

tentei aceder ao forum, mas sem sucesso. Ja agora aproveito para colocar a minha duvida aqui:

Utilizando isto (sim, consegui, ate integrando com um plugin de Jquery para upload, fico lindinho...), como consigo saber se o upload terminou?
Blogger Micox - Náiron J. C. G. disse... 15 Janeiro, 2008 13:10  
Cara, com essa função aí não dá pra saber não. com essa aí você apenas joga o resultado em uma div qualquer.

Esta semana pretendo postar uma versão nova desse upload aí onde será possível saber. Quem tiver pressa me mande um email que eu mando o código.

Galera, a função php pra upload, vocês acham no google pesquisando por Upload php. Simples!
Blogger tiagowanke disse... 21 Janeiro, 2008 15:34  
Muito boa a função, fiquei de cara, vc esta de parabens.
Blogger tiagowanke disse... 21 Janeiro, 2008 15:41  
Estou com um problema, testei no IE6 e da a mensagem de erro que é enviada por parametro para sua função.

Poderia me ajudar?
Meu email: tiagowanke@gmail.com

Agradeço desde já.
Blogger felipe disse... 28 Fevereiro, 2008 20:12  
Fala Micox blz !?
Eu percebi que pode se fazer um multiplo upload, porem, como eu poderia fazer uma verificação nos campos antes de enviar os arquivos ?

email: lfrs_web@yahoo.com.br

Vlw...

ps:belissimo codigo ^^
Blogger Micox - Náiron J. C. G. disse... 29 Fevereiro, 2008 07:19  
Ué.
É só chamar seu código (ou função) que faz a verificação ANTES de chamar minha função. Simples.
(supondo que você JÁ tenha uma função pra verificação)
Blogger stutzinho disse... 15 Março, 2008 00:58  
Micox, só dizer uma coisa: Show de bola!! Simples de usar, de entender, direto ao ponto!! Muiito bom mesmo! Matou a pau!

Abraço!
Blogger donwellus disse... 08 Julho, 2008 08:46  
obrigado por ajudar os reles mortais!!
Blogger Eric Freitas disse... 11 Julho, 2008 13:35  
Muito legal micox, me ajudou muito!
também não tive sucesso com o fórum
e lendo os posts percebi que você ja possui uma nova função de upload melhor que esta ja postada.
Gostaria de saber se esta ja esta pronta e queria analisa-la para ver qual se enquadra mais às minha necessidades.
Se puder me enviar esta outra no meu e-mail agradeço: eric_freitas@hotmail.com
------------------
dúvida sobre a função:
O resultado retornado na div/span é o retorno do meu PHP?
->Pq como vou usar com ajax, preciso do endereço da foto para enviar pro banco...

Muito Obrigado.
Att. Eric Rodrigo de Freitas
Blogger Belchior Pereira de Araujo disse... 07 Agosto, 2008 11:48  
Parabéns! Funcionou beleza! Com firefox 3. Valeu!
Blogger Leandro disse... 10 Agosto, 2008 16:49  
ei Micox, parabens pelo topico.

quase 1 ano e meio depois esse topico me ajudou.

Parabens pela iniciativa
Blogger Alberto disse... 10 Setembro, 2008 09:12  
Mano blz teu esquema funciona certinho so to com um problema não sei se é falta de entendimento do negocio mais quando eu envio o upload e ele esta dentro de um form para envio de outros campos depois de enviar o up o action do meu form para que muda e fica como o action do upload não sei se fui muito claro mais ai esta meu email ok se puder entrar em contato

email/msn: a2web@a2web.com.br
Blogger Jéter Ornelas Oliveira Alves disse... 03 Outubro, 2008 10:04  
Excelente seu artigo! não tive problemas em implementar na minha aplicação! Parabéns! Nota 1000!!!!
Blogger Rafa disse... 15 Outubro, 2008 20:37  
Esta postagem foi removida pelo autor.
Blogger Rafa disse... 15 Outubro, 2008 20:39  
Mto bom msmo, mas naum consegui colocar uma imagem no codigo...
ex: micoxUpload(this.form,'cad_foto.php','recebe_up_basico',
'espera.gif','Erro ao carregar'); return false;"...

ele exibe somente o texto "espera.gif", a imagem está no mesmo diretorio do html.
Blogger Micox - Náiron J. C. G. disse... 16 Outubro, 2008 07:26  
Ué Rafa, é só colocar a tag img inteira ué.
Anonymous Flávio Tunpaio disse... 11 Janeiro, 2009 11:26  
Gostei, to tentando usar, só queria saber onde está a versão 2.0?

Mesmo assim agradeço
Anonymous Aline EA Rigues disse... 14 Janeiro, 2009 15:58  
Olá! Sou Aline Amaral Rigues e vim agradecer a sua contribuição para nós programadores com o código apresentado! Agradeço veemente!
Um grande abraço!
Blogger Allan Borges disse... 12 Março, 2009 15:57  
Noh cara vlw d+,vou usar elas !
flwss abrass
Blogger Abdoral disse... 13 Maio, 2009 13:37  
Eh possivel aplicar esse codigo, usando Jquery?!
Blogger Micox - Náiron J. C. G. disse... 13 Maio, 2009 13:45  
Sim, é possível usar com jquery, mas acredito que o jquery tem seus próprios plugins para isso.

Uma versão mais atualizada também pode ser vista aqui: http://webly.com.br/Micox/micoxUpload2.htm
Blogger Diego disse... 26 Junho, 2009 15:17  
Esta postagem foi removida pelo autor.

Escreva seu comentário (Leia abaixo).

Deixe seu email se quiser resposta por email também, pois o sistema de comentários do Blogger não me informa :( ... Ah, também pode deixar o endereço do seu blog ou site no comentário.
Já estou em outro sistema de blog melhor (wordpress). Se quiser comentar lá também :)
Dúvidas, só no fórum Webly.

Links para este post:

<< Ir à página principal e ver as novas postagens.

El Micox - Alguns direitos resevados - Licença Creative Commons

Veja! Este é apenas um espelho do blog real elmicox.com. Assinando aqui, na verdade você está assinando lá.