Abrir caixa de diálogo de arquivo em JavaScript

109

Preciso de uma solução para exibir a caixa de diálogo de arquivo aberto em HTML enquanto clico em a div. A caixa de diálogo para abrir arquivo deve ser aberta quando o divfor clicado.

Não quero exibir a caixa do arquivo de entrada como parte da página HTML. Deve ser exibido em uma caixa de diálogo separada, que não faz parte da página da web.

Arca
fonte
4
Um alerta não é uma caixa de diálogo de arquivo? - Você pode esclarecer o que está perguntando?
LiamB
3
acho que ele está dizendo que deseja o pop
Valentin Rocher
1
Eu preciso abrir a caixa de diálogo do arquivo quando um div é clicado. deve ser como um alerta que não faz parte da página web
ArK 12/01/10

Respostas:

52

Aqui está um bom

Demonstração do Fine Uploader

É um <input type='file' />controle em si. Mas um div é colocado sobre ele e os estilos css são aplicados para obter essa sensação. A opacidade do controle de arquivo é definida como 0 para que pareça que a janela de diálogo é aberta ao clicar no div.

Rahul
fonte
1
existe uma maneira de controlar os arquivos exibidos por javascript ... digamos que eu queria abrir a caixa de diálogo do arquivo e só queria a extensão do arquivo com .pdf para exibir ..
Ajax3.14
1
@ Ajax3.14 novos navegadores tem o objeto FileReader, navegadores antigos você tem que usar o valor e procurar a extensão do arquivo.
Vicary
2
@ Ajax3.14 Não há necessidade de usar FileReader ou extensões de análise. Muitos navegadores suportam o atributo accept em entradas de arquivo. Isso permite que você limite os tipos de arquivo exibidos na caixa de diálogo do navegador de arquivos. O Fine Uploader fornece acesso a essa funcionalidade por meio da propriedade acceptFiles da opção de validação. Consulte a seção de validação da documentação de opções para obter mais detalhes. Observe que o atributo accept não é compatível com o IE9 ou anterior.
Ray Nicholus
1
como é que isso é bom? esta é uma boa prática? não deveria ser algo assim: stackoverflow.com/a/18659941/915865 ?
Kat Lim Ruiz
1
@KatLimRuiz Não, a resposta que você vinculou não é uma boa solução. Isso fará com que o IE gere um erro se você também enviar o formulário associado de maneira programática.
Ray Nicholus,
77

    $("#logo").css('opacity','0');
    
    $("#select_logo").click(function(e){
       e.preventDefault();
       $("#logo").trigger('click');
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" id="select_logo">Select Logo</a> <input type="file" id="logo">

para o IE adicione isto:

$("#logo").css('filter','alpha(opacity = 0');
Somwang Souksavatd
fonte
3
Por que você retorna false no #select_logo manipulador de cliques?
Sethish
4
Não produziria um erro 404, apenas tentaria navegar para a página atual, com o # adicionado no final. O que faria a página saltar para o topo. Então é bom estar lá, só por um motivo diferente :)
manavo 09/01/2013
3
Embora eu não tenha testado o suficiente, "visibilidade: oculto;" parece mais compatível. Além disso, apesar de opacity: 0, um evento de clique será disparado se o elemento "invisível" for clicado, enquanto a visibilidade: oculto não.
Aron
MDN indica que document.getElementById("logo").click()é o suficiente. Eles também mostram outra forma de "arrastar e soltar". developer.mozilla.org/en-US/docs/Web/API/File/…
Eric
2
Você deve converter isso para Javascript normal, JQuery não é lógico para usar em um projeto tão pequeno ^ _ ^
Senhor SirCode
57

Não sei por que ninguém apontou isso, mas aqui está uma maneira de fazer isso sem qualquer Javascript e também é compatível com qualquer navegador.


EDIT: No Safari, o inputé desativado quando escondido com display: none. Uma abordagem melhor seria usar position: fixed; top: -100em.


<label>
  Open file dialog
  <input type="file" style="position: fixed; top: -100em">
</label>

Se preferir, você pode ir a "maneira correta" , usando forna labelapontando para a idda entrada como esta:

<label for="inputId">file dialog</label>
<input id="inputId" type="file" style="position: fixed; top: -100em">
JP de la Torre
fonte
4
isso funciona como um charme, entretanto, aqui estão algumas recomendações: 1. <input>tag deve ter nameatributo; 2. se o foratributo for especificado, a <input>tag do arquivo exigirá um id.
Raptor
5
Simplicity is the ultimate sophistication
ncubica
2
ótimo! funciona muito bem mesmo com uma imagem de fundo ou fazendo com que o rótulo receba um clique do javascript acionado. Obrigado!
Leo Nomdedeu
2
BTW, alguém apontou um problema com esta solução, no Safari, as entradas ocultas com display: noneestão desabilitadas. A solução alternativa é usar uma abordagem diferente para ocultar a entrada. Vou atualizar a resposta para refletir isso.
JP de la Torre,
1
@JPdelaTorre Seria muito melhor se você usasse opacity: 0 em vez de ocultar a entrada.
Adrian
39

Na verdade, você não precisa de tudo isso com opacidade, visibilidade, <input>estilo etc. Basta dar uma olhada:

<a href="#">Just click me.</a>
<script type="text/javascript">
    $("a").click(function() {
        // creating input on-the-fly
        var input = $(document.createElement("input"));
        input.attr("type", "file");
        // add onchange handler if you wish to get the file :)
        input.trigger("click"); // opening dialog
        return false; // avoiding navigation
    });
</script>

Demo em jsFiddle . Testado no Chrome 30.0 e Firefox 24.0. Não funcionou no Opera 12.16, no entanto.

Tigran Saluev
fonte
3
Esta deve ser a resposta correta. Para implementação de Javascript pura, não é necessário modificar nenhum código HTML.
Zhang Buzz
21
Pergunta boba, mas como você obteria o arquivo escolhido depois?
Jay Wick
2
Esta é uma solução perigosa que pode resultar em problemas inesperados. Por exemplo, alguns navegadores (como o IE) podem impedir um envio de formulário programático se a entrada do arquivo também for aberta programaticamente. A melhor maneira de resolver esse problema é com CSS, não JavaScript.
Ray Nicholus
3
@Charleston Infelizmente, não funciona em alguns navegadores. Eles deveriam fazer funcionar :)
Tigran Saluev
3
Em 2020, essa solução parecia a melhor. Testei no BrowserStack no Edge, Safari, Opera, Firefox e Chrome. Funciona em todos eles.
V. Rubinetti
14

Isso é o que funcionou melhor para mim (testado no IE8, FF, Chrome, Safari).

#file-input {
  cursor: pointer;
  outline: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  overflow: hidden;
  filter: alpha(opacity=0); /* IE < 9 */
  opacity: 0;
}
.input-label {
  cursor: pointer;
  position: relative;
  display: inline-block;
}
<label for="file-input" class="input-label">
  Click Me <!-- Replace with whatever text or icon you wish to use -->
  <input type="file" id="file-input">
</label>

Explicação: Posicionei a entrada do arquivo diretamente acima do elemento a ser clicado, de forma que qualquer clique iria parar nele ou em seu rótulo (que abre a caixa de diálogo de upload como se você clicasse no próprio rótulo). Tive alguns problemas com a parte do botão da entrada padrão saindo da lateral da etiqueta, portanto, overflow: hiddena entrada e display: inline-blocka etiqueta eram necessárias.

Chris
fonte
1
Maximize a entrada e defina a opacidade para zero. Isso funciona muito bem!
Kinorsi
13

E se o javascript estiver desligado na máquina do cliente? Use a solução a seguir para todos os cenários. Você nem precisa de javascript / jQuery. :

HTML

<label for="fileInput"><img src="File_upload_Img"><label>
<input type="file" id="fileInput"></label>

CSS

#fileInput{opacity:0}  
body{
    background:cadetblue;
}

Explicação: for="Your input Id". Aciona o evento de clique por padrão em HTML. Portanto, por padrão, ele aciona o evento de clique, sem necessidade de jQuery / javascript. Se é feito simplesmente por HTML, por que usar jQuery / jScript? E você não pode dizer se o cliente desabilitou JS. Seu recurso deve funcionar mesmo que o JS esteja desligado.

Trabalhando jsFiddle (você não precisa de JS, jquery)

Pratik
fonte
3
Por que o fundo?
Solomon Ucko
12

Primeiro adicione as tags head :

<script>
   function showDialog(openFileDialog) {
       document.getElementById(openFileDialog).click();
   }
   function fileName(openFileDialog) {
       return document.getElementById(openFileDialog).value;
   }
   function hasFile(openFileDialog) {
       return document.getElementById(openFileDialog).value != "";
   }
   function fileNameWithoutFakePath(openFileDialog) {
       var fileName = document.getElementById(openFileDialog).value;
       return fileName.substr(fileName.lastIndexOf('\\') + 1);
   }
   function fakePathWithoutFileName(openFileDialog) {
       var fileName = document.getElementById(openFileDialog).value;
       return fileName.substr(0, fileName.lastIndexOf('\\'));
   }
</script>

se você já tem script tags de , basta adicionar as funções acima.

Em suas tags de corpo ou formulário, adicionando:

<input type="file" style="display:none" id="yourDesiredOrFavoriteNameForTheNewOpenFileDialogInstance"/>

Não importa onde em seu html, é exatamente assim que você criou uma nova instância do tipo OpenFileDialog class como variável global , cujo nome é o id do elemento, não importa onde em seu código ou xaml, mas em seu script ou código você não pode digitar o nome dele e depois ler uma propriedade ou chamar uma função, porque existem funções globais que fazem aquelas que não estão definidas no elemento input type = "file". Você só precisa fornecer a essas funções o id do tipo de entrada oculto = "arquivo" que é o nome da instância OpenFileDialog como string.

Para facilitar sua vida na criação de instâncias de diálogos de arquivos abertos para o seu html, você pode criar uma função que o faça:

function createAndAddNewOpenFileDialog(name) {
     document.getElementById("yourBodyOrFormId").innerHtml += "<input type='file' style='display:none' id='" + name + "'/>"
}

e se quiser remover a caixa de diálogo de arquivo aberto, você pode criar e usar a seguinte função:

function removeOpenFileDialog(name) {
    var html = document.getElementById("yourBodyOrFormId").innerHtml;
    html = html.replace("<input type='file' style='display:none' id='" + name + "'/>", "");
    document.getElementById("yourBodyOrFormId").innerHtml = html;
}

mas antes de remover a caixa de diálogo de arquivo aberto, verifique se ela existe criando e usando a seguinte função:

function doesOpenFileDialogExist(name) {
    return document.getElementById("yourBodyOrFormId").innerHtml.indexOf("<input type='file' style='display:none' id='" + name + "'/>") != -1
}

e se você não quiser criar e adicionar as caixas de diálogo de arquivo aberto nas tags do corpo ou do formulário no html, porque isso está adicionando tipo de entrada oculto = "arquivo" s, então você pode fazer isso no script usando a função criar acima :

function yourBodyOrFormId_onload() {
    createAndAddNewOpenFileDialog("openFileDialog1");
    createAndAddNewOpenFileDialog("openFileDialog2");
    createAndAddNewOpenFileDialog("openFileDialog3");
    createAndAddNewOpenFileDialog("File Upload");
    createAndAddNewOpenFileDialog("Image Upload");
    createAndAddNewOpenFileDialog("bla");
    //etc and rest of your code
}

Certifique-se de que próximo ao seu corpo ou tags de formulário, você adicionou:

onload="yourBodyOrFormId_onload()"

Você não precisa fazer esta linha acima, se você já fez.

DICA: você pode adicionar ao seu projeto ou site um novo arquivo JScript, se ainda não o fez, e neste arquivo você pode colocar todas as funções de diálogo de arquivo aberto longe das tags de script e da página html ou formulário da web e usar eles em seu html ou página de formulário da web a partir deste arquivo JScript, mas não se esqueça antes de vincular o html ou página de formulário da web ao arquivo JScript, é claro. Você pode fazer isso arrastando o arquivo JScript para a sua página html no cabeçalhoTag. Se a sua página for um formulário da web e não um html simples, e você não tiver tags head, coloque-a em qualquer lugar para que funcione. Não se esqueça de definir a variável global nesse arquivo JScript, cujo valor será seu corpo ou id de formulário como string. Depois de vincular o arquivo JScript ao seu html ou página de formulário da web, você pode carregar o evento de seu corpo de formulário, definir o valor dessa variável para seu corpo ou id de formulário. Então, no arquivo JScript, você não precisa mais dar ao documento o id do corpo ou forma de uma página, apenas dê a ele o valor daquela variável. Você pode chamar essa variável de bodyId ou formId ou bodyOrFormId ou qualquer outro nome que desejar.

Boa sorte rapaz!


fonte
1
É melhor não modificar diretamente o innerHTML.
Solomon Ucko
9

A maneira mais simples:

#file-input {
  display: none;
}
<label for="file-input">
  <div>Click this div and select a file</div>
</label>
<input type="file" id="file-input"/>

O que é importante, o uso de display: nonegarante que nenhum lugar será ocupado pela entrada do arquivo oculto (o que acontece usando opacity: 0).

Karol Selak
fonte
3

AFAIK você ainda precisa de um <input type="file">elemento, então você pode usar algumas das coisas do quirksmode para estilizá -lo

Dan F
fonte
2

O único sem <input type="file">é incorporar um filme flash transparente sobre o div. Você pode então usar um evento de clique gerado pelo usuário (compatível com as novas regras de segurança do Flash 10) para acionar uma chamada para FileReference.browse do flash .

Ele oferece uma dependência adicional em relação ao modo quirksmode, mas em troca você obtém muitos mais eventos (como eventos de progresso embutidos).

Martijn Laarman
fonte
-1

Pode utilizar

$('<input type="file" />').click()
Hamed Zakery Miab
fonte
no meu caso, isso causa um redirecionamento automático para a mesma página onde o evento de clique original aconteceu - fazendo toda a página recarregar e perder todos os dados inseridos anteriormente na página.
Muntasir