Enviando vários arquivos sem exibir input file

Dia 06/07/2007 na lista Webstandards-br foi questionado como o gmail fazia, para que sem o input file, fosse enviado arquivo. Porém isso só acontecia no IE, no Firefox era um input normal.O pessoal deu uma olhada no código e concluiu que no IE funcionava algo como:

JavaScript:
  1. document.getElementById('InputFile').click();

Porém no Firefox isso não funciona. Não querendo entrar no mérito de qual navegador está certo, pensei em um modo de driblar isso e o resultando acabou resultando neste artigo.

Como fazer

Minha idéia para contornar isso é utilizar um input que fique transparente e colocar uma imagem no fundo do elemento onde esse input está! Veja que não podemos esconder o input, pois ele precisa ser clicado, mas sem que o usuário perceba. Então vamos ao HTML básico:

HTML:
  1. <form method="post" enctype="multipart/form-data" id="UploadForm">
  2. <p id="uploadButton"> <input id="inputFile" name="inputFile" size="1" type="file" /></p>
  3.  
  4. </form>

Temos um div chamado uploadButton, que conterá a imagem de fundo e o input que fará a coisa acontecer.

Adicionamos um pouco de CSS:

CSS:
  1. #inputFile {
  2.   float: right;
  3.   opacity: 0;
  4.   filter: alpha(opacity=0);
  5. }
  6. #uploadButton {
  7.   width:88px;
  8.   height:20px;
  9.   background:url("adicionar.jpg") no-repeat;
  10.   float:left;
  11.   margin: 0 20px 0 0;
  12. }
  13. #files {
  14.   clear:both;
  15. }

Veja que no #inputFile definimos opacity, para funciona no Firefox e um filter para ficar transparente no IE. O #files veremos pra que serve daqui a pouco.

Fazendo a mágica acontecer com javascript

Utilizei a jQuery por pura comodidade, mas poderia facilmente ser feito na mão. Na verdade para enviar um arquivo precisariamos do javascript apenas para exibir o nome do arquivo em algum lugar. Mas como queremos fazer o upload de vários arquivos:

JavaScript:
  1. var InputCount=1;
  2. $(function() {
  3. $("#UploadForm").append("&lt;ul id='files'&gt;&lt;/ul&gt;");
  4. $("#inputFile").change( function() { newFile(); } );
  5. });
  6. function newFile() {
  7. $("#files").append("&lt;li&gt;" + $("#inputFile").val() + "&lt;/li&gt;");
  8. $("#inputFile").hide();
  9. $("#inputFile").clone().appendTo("#uploadButton");
  10. $("#inputFile").attr("id", "inputFile" + InputCount);
  11. $("#inputFile" + InputCount).attr("name", "inputFile" + InputCount);
  12. InputCount++;
  13. $("#inputFile").change( function() { newFile(); } );
  14. $("#inputFile").val("");
  15. $("#inputFile").show();
  16. }

Para ver tudo funcionando acesse o exemplo.
Para finalizar ainda seria necessário adicionar um botão de submit e tratar o retorno no servidor. Porém isso não será tratado aqui!

Após escrever todo o exemplo e o artigo, resolvi testar no IE6 (o que devia ter sido feito antes) e percebi que não funcionava o filtro da opacidade, apesar de tudo dar certo no IE 5 e no IE 7. Estou com o tempo curto e se você descobrir como resolver, poste um comentário.

9 Comentários

  1. Israel Cefrin escreveu em 09 de julho de 2007 as 10:05:

    Cara
    Excelente artigo.
    Vi que usaste jQuery, esse bichinho é bom mesmo.

    abraços
    Israel

  2. Fill escreveu em 22 de agosto de 2007 as 13:55:

    Boa.. Gostei do script. Estiloso =) Vai pro del.icio.us =) Vlw a dica.

  3. Ricardo Floriano escreveu em 11 de setembro de 2007 as 11:15:

    Cara com o problema do transparent usa um background .gif com transparencia, pode ser 1px por 1px. Tive esse problema com um menu de arvore que não podia ter fundo…

  4. Tudo sobre jQuery - Cleiton.net escreveu em 18 de maio de 2008 as 20:18:

    [...] Enviando vários arquivos sem exibir input file [...]

  5. Leandro Rodrigues escreveu em 17 de julho de 2008 as 19:21:

    Oi, bom seu artigo é muito bom. Mas mesmo assim o firefox não mostra o caminho da imagem, ou seja, não é possível fazer o upload do arquivo…

    Existe alguma forma?

  6. Felipe Diesel escreveu em 18 de julho de 2008 as 08:02:

    Leandro,
    Como assim não mostra o caminho. É colocado um input file oculto no código onde está o caminho. veja o exemplo e desative o CSS que você vai ver que esta tudo lá.

  7. Rafael Rocha escreveu em 22 de julho de 2008 as 18:08:

    Leandro, na tag de abertura do seu form coloca o atributo enctype=”multipart/form-data” que no firefox aparece o caminho do arquivo como vc quer.. quebrei a cara com isso ja e nao custa ajudar quem anda quebrando agora ne rs..
    abraços!

  8. Rafael Rocha escreveu em 22 de julho de 2008 as 18:21:

    blz agora como fazer pra excluir um arquivo da lista caso não queira mais enviá-lo?

  9. Vagner escreveu em 25 de agosto de 2008 as 22:21:

    valeu pelo enctype=”multipart/form-data” mas p/ mim ainda não funfou na raposa, talvez pq eu esteja usando master page (manjo pouco de web, então..) mesmo assim, valeu.

Deixe seu comentário