Entrada do arquivo acionador jQuery

163

Estou tentando acionar uma caixa de upload (botão de navegação) usando o jQuery.
O método que eu tentei agora é:

$('#fileinput').trigger('click');   

Mas isso não parece funcionar. Por favor ajude. Obrigado.

Alec Smart
fonte
Você pode tentar algo parecido com isto .
Kirtan
19
Não tem como fazer isso? Que deprimente.
Marcus Downing
Deprimente de fato, e é acionado por 'clique', sério? Eu prefiro o Flash / AS3, com sua API rígida e um forte modelo de segurança que só permite que o FileReference.browse seja chamado de um manipulador de eventos de entrada iniciado pelo usuário. Além disso, a entrada do arquivo HTML é feia e pouco estilizada (é apenas uma tag de entrada, tanto para separação de conteúdo e estilo), então você precisa criar um novo botão 'navegar', que também é ativado por um evento de clique ... que você deve encaminhar para a entrada do arquivo como um clique ... o que pode levar a uma recursão infinita, dependendo do posicionamento do elemento e da especificidade da delegação de eventos.
Triynko
Infelizmente, o uso do Flash está se tornando cada vez menos viável, dados os constantes problemas de segurança e o aumento dos bloqueadores de conteúdo.
Tim

Respostas:

195

Isso ocorre devido a uma restrição de segurança.

Eu descobri que a restrição de segurança é apenas quando o <input type="file"/>está definido como display:none;ou está visbilty:hidden.

Então, eu tentei posicioná-lo fora da janela, definindo position:absolutee top:-100px;e voilà ele funciona.

veja http://jsfiddle.net/DSARd/1/

chame de hack.

Espero que funcione para você.

adardesign
fonte
4
não funciona no ff 3.6. obras em cromo e até mesmo no IE 8 embora :)
AyKarsi
4
Existe alguma documentação no msdn sobre a restrição de segurança?
eomeroff
2
Funciona bem. Em qualquer caso, eu acho que é mais seguro definir um left: -100px;. Você nunca sabe quanto tempo poderia ser uma página
Alter Lagos
+1 Esta é a resposta real (e uma boa solução). Alguém teria um link para a documentação onde isso é explicitamente declarado?
kontur
9
você também pode definir a opacidade como 0
Stuart
109

isso funcionou para mim:

JS:

$('#fileinput').trigger('click'); 

HTML:

<div class="hiddenfile">
  <input name="upload" type="file" id="fileinput"/>
</div>

CSS:

.hiddenfile {
 width: 0px;
 height: 0px;
 overflow: hidden;
}

>>> Outro que funciona em vários navegadores: <<<

A idéia é que você sobreponha um enorme botão "Procurar" invisível sobre o botão personalizado. Portanto, quando o usuário clica no botão personalizado, na verdade, ele está clicando no botão "Procurar" do campo de entrada nativo.

JS Fiddle: http://jsfiddle.net/5Rh7b/

HTML:

<div id="mybutton">
  <input type="file" id="myfile" name="upload"/>
  Click Me!
</div>

CSS:

div#mybutton {

  /* IMPORTANT STUFF */
  overflow: hidden;
  position: relative;   

  /* SOME STYLING */
  width:  50px;
  height: 28px;
  border: 1px solid green;
  font-weight: bold
  background: red;
}

div#mybutton:hover {
  background: green;
}

input#myfile {
  height: 30px;
  cursor: pointer;
  position: absolute;
  top: 0px;
  right: 0px;
  font-size: 100px;
  z-index: 2;

  opacity: 0.0; /* Standard: FF gt 1.5, Opera, Safari */
  filter: alpha(opacity=0); /* IE lt 8 */
  -ms-filter: "alpha(opacity=0)"; /* IE 8 */
  -khtml-opacity: 0.0; /* Safari 1.x */
  -moz-opacity: 0.0; /* FF lt 1.5, Netscape */
}

JavaScript:

$(document).ready(function() {
    $('#myfile').change(function(evt) {
        alert($(this).val());
    });
});
trenó
fonte
Há uma falha: se você aumentar o botão, no IE9 / 10, o botão invisível de upload será feito do botão direito e do campo de texto esquerdo. Neste você tem que clicar duas vezes. Nesse caso, tente definir o tamanho da fonte ainda maior que 100px;
yunzen
Isso funciona mesmo no Chrome 53. No entanto, heighté sugerido que você mude paraheight: 100%
Raptor
O segundo ainda funciona no Safari no iOS. Muito agradável!
Jannis
71

Você pode usar o elemento LABEL ex.

<div>
    <label for="browse">Click Me</label>
    <input type="file" id="browse" name="browse" style="display: none">//
</div>

Isso acionará o arquivo de entrada

Jhon Rey
fonte
5
Por que essa não é a resposta aceita? É a maneira mais simples que não requer javascript funky.
tomitrescak
@tomitrescak, o OP não está esperando a melhor resposta.
Mahi
9
Lembre-se de que a resposta foi publicada sete anos após o envio da pergunta.
1
Melhor resposta em 2018 também.
Masoomyf
1
Melhor resposta para 2019 também;)
guillaumepotier
17

Eu tenho que trabalhar (= testado) no IE8 +, recente FF e chrome:

$('#uploadInput').focus().trigger('click');

A chave está focada antes de disparar o clique (caso contrário, o Chrome o ignora).

Nota: você PRECISA ter sua entrada exibida e visível (como em, não display:nonee não visibility:hidden). Sugiro (como muitos outros já fizeram) posicionar absolutamente a entrada e jogá-la para fora da tela.

#uploadInput {
    position: absolute;
    left: -9999px;
}
O poderoso pato de borracha
fonte
1
+1 para isso. Também notei que você pode ocultar o elemento circundante, mas não o botão de entrada do arquivo, mostrar o elemento circundante, focalizar o botão, ativá-lo e ocultar o botão.
Stevo
10

Veja meu violino.

http://jsfiddle.net/mohany2712/vaw8k/

.uploadFile {
  visibility: hidden;
}

#uploadIcon {
  cursor: pointer;
}
<body>
  <div class="uploadBox">
    <label for="uploadFile" id="uploadIcon">
      <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Icon_-_upload_photo_2.svg/512px-Icon_-_upload_photo_2.svg.png"  width="20px" height="20px"/>
    </label>
    <input type="file" value="upload" id="uploadFile" class="uploadFile" />
  </div>
</body>

Mohan
fonte
9

adardesign acertou em cheio o elemento de entrada do arquivo que está sendo ignorado quando está oculto. Também notei muitas pessoas mudando o tamanho do elemento para 0 ou empurrando-o para fora dos limites com ajustes de posicionamento e transbordamento. Todas essas são ótimas idéias.
Uma maneira alternativa que também parece funcionar perfeitamente bem é definir a opacidade como 0 . Em seguida, você sempre pode definir a posição para evitar que outros elementos sejam compensados, como o hide faz. Parece um pouco desnecessário deslocar um elemento quase 10K pixels em qualquer direção.

Aqui está um pequeno exemplo para quem quer um:

input[type='file']{
    position:absolute;
    opacity:0;
    /* For IE8 "Keep the IE opacity settings in this order for max compatibility" */
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    /* For IE5 - 7 */
    filter: alpha(opacity=0);
}
eyegropram
fonte
7

Por uma questão de curiosidade, você pode fazer o que quiser, criando dinamicamente um formulário de upload e um arquivo de entrada, sem adicioná-lo à árvore do DOM:

$('.your-button').on('click', function() {
    var uploadForm = document.createElement('form');
    var fileInput = uploadForm.appendChild(document.createElement('input'));

    fileInput.type = 'file';
    fileInput.name = 'images';
    fileInput.multiple = true;

    fileInput.click();
});

Não é necessário adicionar o uploadForm ao DOM.

jairhumberto
fonte
1
OBRIGADO! Estou procurando por isso há 20 minutos!
Labo
5

Código correto:

<style>
    .upload input[type='file']{
        position: absolute;
        float: left;
        opacity: 0; /* For IE8 "Keep the IE opacity settings in this order for max compatibility" */
        -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* For IE5 - 7 */
        filter: alpha(opacity=0);
        width: 100px; height: 30px; z-index: 51
    }
    .upload input[type='button']{
        width: 100px;
        height: 30px;
        z-index: 50;
    }
    .upload input[type='submit']{
        display: none;
    }
    .upload{
        width: 100px; height: 30px
    }
</style>
<div class="upload">
    <input type='file' ID="flArquivo" onchange="upload();" />
    <input type="button" value="Selecionar" onchange="open();" />
    <input type='submit' ID="btnEnviarImagem"  />
</div>

<script type="text/javascript">
    function open() {
        $('#flArquivo').click();
    }
    function upload() {
        $('#btnEnviarImagem').click();
    }
</script>
E9 Sistemas
fonte
4

Isso é proposital e por design. É uma questão de segurança.

Chad Grant
fonte
4

Na verdade, descobri um método muito fácil para isso, que é:

$('#fileinput').show().trigger('click').hide();   

Dessa forma, o campo de entrada do arquivo pode ter a propriedade css exibida em none e ainda ganhar o comércio :)

skywlkr
fonte
pode aparecer na tela na máquina mais lenta. Não é uma solução ideal
Dmitry Efimenko
4

É tarde demais para responder, mas acho que essa configuração mínima funciona melhor. Eu também estou procurando o mesmo.

  <div class="btn-file">
     <input type="file" class="hidden-input">
     Select your new picture
  </div>

// css

.btn-file {
  display: inline-block;
  padding: 8px 12px;
  cursor: pointer;
  background: #89f;
  color: #345;
  position: relative;
  overflow: hidden;
}

.btn-file input[type=file] {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 100%;
  min-height: 100%;
  filter: alpha(opacity=0);
  opacity: 0;
  cursor: inherit;
  display: block;
}

jsbin

demo de botões de entrada de arquivo de inicialização

Natwar Singh
fonte
nunca é tarde para responder;);
AGuyCalledGerald 3/14/14
Alguns anos mais tarde ainda melhor resposta IMO
DimmuR
4

Essa é uma pergunta muito antiga, mas infelizmente esse problema ainda é relevante e requer uma solução.

A solução (surpreendentemente simples) que eu encontrei é "ocultar" o campo de entrada do arquivo real e envolvê-lo com uma tag LABEL (pode ser baseada no Bootstrap e HTML5, para aprimoramento).

See here:Exemplo de código aqui

Dessa forma, o campo de entrada do arquivo real é invisível e tudo o que você vê é o "botão" personalizado, que na verdade é um elemento LABEL modificado. Quando você clica nesse elemento LABEL, a janela para selecionar um arquivo é exibida e o arquivo escolhido entra no campo de entrada do arquivo real.

Além disso, você pode manipular a aparência e o comportamento que desejar (por exemplo: obtenha o nome do arquivo selecionado no arquivo de entrada do arquivo, depois de selecionado, e mostre-o em algum lugar. O elemento LABEL não faz isso automaticamente, é claro.Eu geralmente coloco dentro do LABEL, como seu conteúdo de texto).

Cuidado, porém! A manipulação da aparência e do comportamento disso é limitada ao que você possa imaginar e pensar. ;-) ;-)

TheCuBeMan
fonte
3

Eu consegui com um simples $ (...). Click (); com o JQuery 1.6.1

Valentin Galea
fonte
1
Hmm, curioso como você fez isso, no meu site (www.iscriptdesign.com) fazendo um $ ('file: input'). Click () não faz nada, nem $ ('file: input'). Trigger (' clique');
dr jerry
Aqui está o exemplo completo: <input type = "file" id = "picBrowse" ... e depois $ ('# picBrowse'). Click ();
Valentin Galea
Eu testei no cr (não tenho certeza de qual versão) no mac os, funciona no FF 4 no XP. Obrigado!
dr jerry
3

ou então simplesmente

$(':input[type="file"]').show().click().hide();
Otvazhnii
fonte
2

Eu tive problemas com a validação personalizada do lado do cliente <input type="file"/>enquanto usava um botão falso para acioná-lo e a solução do @Guillaume Bodi funcionou para mim (também com o opacity: 0;chrome)

$("#MyForm").on("click", "#fake-button", function () {
        $("#uploadInput").focus().trigger("click");
    });

e estilo css para entrada de upload

#uploadInput {
opacity: 0.0; 
filter: alpha(opacity=0); /* IE lt 8 */
-ms-filter: "alpha(opacity=0)"; /* IE 8 */
-khtml-opacity: 0.0; /* Safari 1.x */
-moz-opacity: 0.0;
}
Amin K
fonte
1

Tente isso, é um hack. a Posição: absoluto é para o Chrome e gatilho ('alteração') é para o IE.

var hiddenFile = $("<input type=\"file\" name=\"file\" id=\"file1\" style=\"position:absolute;left:-9999px\" />");
$('body').append(hiddenFile);

$('#aPhotoUpload').click(function () {
    hiddenFile.trigger('click');
    if ($.browser.msie)
        hiddenFile.trigger('change');
});

hiddenFile.change(function (e) {
    alert('TODO');
});
thinpiglin
fonte
Note-se que $.browseré obsoleto em versões mais recentes do jQuery
Kevin Beal
1

Meu problema era um pouco diferente no iOS 7. Acontece que o FastClick estava causando problemas. Tudo o que eu precisava fazer era adicionar class="needsclick"ao meu botão.

Dex
fonte
0

Esta é provavelmente a melhor resposta, tendo em mente os problemas entre navegadores.

CSS:

#file {
  opacity: 0;
  width: 1px;
  height: 1px;
}

JS:

$(".file-upload").on('click',function(){
   $("[name='file']").click();
});

HTML:

<a class="file-upload">Upload</a>
<input type="file" name="file">
Eddsters
fonte
0

Acho que entendi o seu problema, porque tenho um similar. Para que a tag <label>tenha o atributo, você pode usá-lo para vincular sua entrada com type = "file". Mas se você não deseja ativar isso usando esse rótulo, porque algumas regras do seu layout, você pode fazer assim.

$(document).ready(function(){
  var reference = $(document).find("#main");
  reference.find(".js-btn-upload").attr({
     formenctype: 'multipart/form-data'
  });
  
  reference.find(".js-btn-upload").click(function(){
    reference.find("label").trigger("click");
  });
  
});
.hide{
  overflow: hidden;
  visibility: hidden;
  /*Style for hide the elements, don't put the element "out" of the screen*/
}

.btn{
  /*button style*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<div id="main">
<form enctype"multipart/formdata" id="form-id" class="hide" method="post" action="your-action">
  <label for="input-id" class="hide"></label>
  <input type="file" id="input-id" class="hide"/>
</form>

<button class="btn js-btn-upload">click me</button>
</div>

É claro que você adaptará isso para seu próprio objetivo e layout, mas é a maneira mais fácil que eu conheço para fazê-lo funcionar!

Leonardo Lindroth
fonte
-1

Com base na resposta de Guillaume Bodi, fiz o seguinte:

$('.fileinputbar-button').on('click', function() {
    $('article.project_files > header, article.upload').show();
    $('article.project_files > header, article.upload header').addClass('active');
    $('.file_content, article.upload .content').show();
    $('.fileinput-button input').focus().click();
    $('.fileinput-button').hide();
});

o que significa que está oculto para começar e, em seguida, exibido para o gatilho e oculto novamente imediatamente.

Stevo
fonte