Upload Assíncrono de Arquivos com Mootools

Como todos sabem, Upload com Ajax não é praticável em ambiente web. Existem várias restrições de segurança que impedem que o JavaScript acesse o sistema de arquivos do cliente e envie dados binários através de uma requisição XMLHttpRequest. No entanto, é possível (e sempre foi) fazer Upload Assíncrono de arquivos, utilizando uma técnica até antiga, muito bem explorada por muitos por aí.

Já havia tempo que eu queria escrever esse script, mas a coragem faltava, até que ele me foi necessário. Como uso Mootools, não faria sentido usar funções autônomas, desperdiçando código. Então tomei coragem e fiz. Pronto, nem doeu…

O Código

Meu objetivo, nesse post, não é explicar a lógica por trás do script (farei isso em breve), mas sim deixar o código pronto, e explicar seu uso.

Download Async Upload

Antes de tudo, você precisará da Mootools com os módulos necessários, o que suponho que você já possua. Depois, faça o download do Async Upload. Agora, basta incluir os dois scripts em sua página.

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

Utilização

Como não podia deixar de ser, o script funciona na submissão de um formulário. Ele a intercepta e a envia para um iframe escondido. Pra que tudo isso funcione, temos que definir isso no onSubmit de nosso formulário:

$(window).addEvent("load", function() { // quando terminar de carregar...
  $("seu-formulario").addEvent("submit", function() { // e o nosso formulário for enviado...
    this.upload() // fazemos nosso upload, parecido (mas não é) com Ajax
  })
}

E cadê a URL?

Como a Mootools nos dá muitas opções para trabalhar com DOM, não precisamos definir a URL no script. Essa URL vai ser retirada do próprio formulário, no action:

<form action="http://sua-url-para-envio/upload.php" id="seu-formulario">
  <input type="file" name="fileToUpload" id="fileToUpload" />
</form>

Elemento de Retorno

Muito melhor do que elementos de retorno, podemos definir uma função para tratar o retorno do upload. Para isso, passamos um parâmetro para a função:

$(window).addEvent("load", function() {
  $("seu-formulario").addEvent("submit", function() {
    this.upload({
      "onComplete": function(response) {
        $("elemento_de_retorno").setHTML(response)
      }
    })
  })
}

Com o código acima, o resultado da requisição iria para uma div (ou algum outro elemento) de id “elemento_de_retorno”. É claro, pode-se fazer muito mais, mas fica a seu cargo decidir…

Recebendo o Arquivo

Apesar de assíncrono (ou Ajax disfarçado), esse upload funciona como um upload comum. No PHP, por exemplo, podemos receber o arquivo assim:

move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], "nome_do_arquivo.txt");

Exemplo e Download

Caso queira dar uma olhada, deixei um exemplo na página de downloads. Faça upload de um arquivo qualquer e veja o funcionamento! Caso deseje saber a lógica por trás de tudo isso, aguarde os próximos posts. Até mais!

Posts Relacionados

Postado em maio 08, 2008 às 12:21

Comentários

  1. Bruno Paulino

    Esse efeito fica legal… Há muito tive essa necessidade e utilizando essa idéia. Mas no meu caso, eu tinha um formulário para cadastro, sendo que o upload fazia parte desse formulário.

    Nesse meu cenário, o seu método deveria ser adaptado, certo?


  2. JulioGreff

    @Bruno: Na verdade não, ele submete todo o formulário, e não apenas o upload. Pode usar sem medo! Poderia ser adaptado se você desejasse que o upload fosse feito separado, mas não há necessidade.

    Até mais!


  3. Zé Rodolfo

    Nao funciona no IE 7. Sabe como corrigir isto?
    Tenho algo parecido também aqui, mas ocorre o mesmo problema. Não está funcionando no IE7….
    :/


  4. JulioGreff

    @Zé Rodolfo: fiz testes no IE7 e funcionou perfeitamente, até porque é um comportamento padrão do navegador adaptado. Talvez seu problema seja na configuração ou até no próprio navegador, já que você testou outras soluções que também não deram certo.


  5. Ricardo

    Não funciona no IE7.

    Fiz varios e varios teste e não consegui fazer funcionar no IE 7, dá um erro nessa linha:

    iFrame.contentDocument.body.innerHTML

    Depois que é feito o upload.


  6. Rodrigo

    Olá Julio,
    Aqui tbém não funcionou no IE7.
    Você tem alguma atualização com a correção?
    abraço


  7. Julio Greff

    Pessoal, o script está corrigido. Me passei na hora de pegar o innerHTML do documento, estava usando o contentDocument, que não funciona no IE. Corrigido!

    Até mais!


  8. Ricardo

    Oi Julio.

    O exemplo ainda tem a versão antiga mas com a correcção funciona 100%.

    Tenho um problema estranho: se colocar todo o exemplo isolado funciona, mas se inserir dentro da minha página, quando se carrega no botão ele limpa o écran com:

    Você enviou o arquivo , com bytes, do tipo
    Warning: unlink() [function.unlink]: No error in C:\xampp\htdocs\jobopera\v1\system\application\helpers\my_photo_upload.php on line 3

    Fazes ideia do erro?!?

    Código:

    $(window).addEvent(“load”, function() {
    $(“file”).addEvent(“submit”, function(e) {

    this.upload({
    “onComplete”: function(e) {
    $(“results”).setHTML(e)
    }
    })
    })
    });

    Photo Image

    Arquivo:

     

    <!–

    Arquivo:

     

    –>


  9. Julio Greff

    Ricardo, seu problema é com PHP, e não com JavaScript. Assim, no escuro, não tenho como lhe dizer como resolver, precisaria de mais informações.


  10. zorooo

    The following version works for me with mootools 1.2.1:

    Element.implement({

    “upload”: function(options) {

    if(this.get(‘tag’) != “form”) return false

    var iFrame = new Element(“iframe”, {

    “id”: “fileUpload”,

    “name”: “fileUpload”,

    “styles”: { “display”: “none” }

    })

    this.adopt(iFrame)

    window.frames["fileUpload"].name = “fileUpload”

    iFrame.addEvent(“load”, function() {

    iFrame.removeEvent(“load”, arguments.callee)

    if($type(options.onComplete) == “function”) {

    options.onComplete(iFrame.contentWindow.document.body.innerHTML)

    }

    iFrame.erase.delay(20, iFrame)

    })

    this.setProperties({

    “target”: “fileUpload”,

    “enctype”: “multipart/form-data”,

    “encoding”: “multipart/form-data”,

    “method”: “post”

    })

    return this

    }

    })

    thx zorooo


  11. Gastão Brun

    Julio, valeu pelo script, muito bom. Percebi que vc usou mootools 1.1, e o zoroo já postou um update para mootools 1.2. Funcionou pra mim legal, mas com um unico probleminha que nao estou conseguindo matar.
    Assim que termina o upload, o cursor continua no estilo ampulheta, como se o browser ainda estivesse esperando o request terminar. Parece que ficou faltando alguma coisa.
    Pode ajudar?
    Valeu,
    Gastão


Deixe seu comentário