Wejście pliku wyzwalacza jQuery


163

Próbuję wywołać okno przesyłania (przycisk przeglądania) za pomocą jQuery.
Metoda, którą teraz wypróbowałem, to:

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

Ale to nie działa. Proszę pomóż. Dziękuję Ci.


Można spróbować czegoś podobnego to zamiast.
Kirtan

19
Nie da się tego zrobić? Jakie to przygnębiające.
Marcus Downing

Rzeczywiście przygnębiające i wywoływane przez „kliknięcie”, poważnie? Zdecydowanie wolę Flash / AS3, z jego ścisłym API i silnym modelem bezpieczeństwa, który umożliwia wywoływanie FileReference.browse tylko z modułu obsługi zdarzeń wejściowych zainicjowanego przez użytkownika. Co więcej, dane wejściowe w pliku HTML są brzydkie i nie można ich napisać (to tylko znacznik wejściowy, tyle dla oddzielenia treści i stylu), więc musisz utworzyć nowy przycisk `` przeglądaj '', który jest również aktywowany przez zdarzenie kliknięcia ... które musisz przekazać do pliku wejściowego jako kliknięcie ... co może prowadzić do nieskończonej rekurencji w zależności od umiejscowienia elementu i specyfiki delegowania zdarzenia.
Triynko

Niestety, używanie Flasha staje się coraz mniej opłacalne, biorąc pod uwagę jego ciągłe problemy z bezpieczeństwem i wzrost liczby blokerów treści.
Tim

Odpowiedzi:


195

Wynika to z ograniczeń bezpieczeństwa.

Dowiedziałem się, że ograniczenie bezpieczeństwa występuje tylko wtedy, gdy <input type="file"/>jest ustawione display:none;lub jest visbilty:hidden.

Spróbowałem więc umieszczenie go na zewnątrz przez ustawienie rzutni position:absolutei top:-100px;i voilà to działa.

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

nazwij to hackem.

Mam nadzieję, że to działa dla Ciebie.


4
nie działa w ff 3.6. działa w chrome a nawet w np. 8 :)
AyKarsi

4
Czy w witrynie msdn jest dostępna dokumentacja dotycząca ograniczenia zabezpieczeń?
eomeroff

2
Działa świetnie. W każdym razie myślę, że bezpieczniej jest ustawić left: -100px;. Nigdy nie wiadomo, jak długo może być stroną
Alter Lagos

+1 To jest prawdziwa odpowiedź (i dobre rozwiązanie). Czy ktoś miałby link do dokumentacji, w której jest to wyraźnie określone?
kontur

9
możesz również ustawić krycie na 0
Stuart

109

to zadziałało dla mnie:

JS:

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

HTML:

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

CSS:

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

>>> Kolejny, który działa w różnych przeglądarkach: <<<

Chodzi o to, aby nałożyć niewidoczny ogromny przycisk „Przeglądaj” na przycisk niestandardowy. Kiedy więc użytkownik kliknie przycisk niestandardowy, w rzeczywistości klika przycisk „Przeglądaj” w natywnym polu wejściowym.

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());
    });
});

Jest jedna wada, jeśli rozszerzysz przycisk, to w IE9 / 10 niewidoczny przycisk przesyłania składa się z prawego przycisku i lewego pola tekstowego. Na to musisz dwukrotnie kliknąć. W takim przypadku spróbuj ustawić rozmiar czcionki nawet większy niż 100px;
yunzen

Działa to nawet w Chrome 53. Jednak heightsugeruje się zmianę naheight: 100%
Raptor

Drugi działa nawet w Safari na iOS. Bardzo dobrze!
Jannis

71

Możesz użyć elementu LABEL np.

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

Spowoduje to uruchomienie pliku wejściowego


5
Dlaczego nie jest to akceptowana odpowiedź? To najprostszy sposób, który nie wymaga funky JavaScript.
tomitrescak

@tomitrescak OP nie czeka na uzyskanie najlepszej odpowiedzi.
Mahi,

9
Pamiętaj, że odpowiedź została opublikowana 7 lat po zadaniu pytania.

1
Najlepsza odpowiedź również w 2018 roku.
masoomyf

1
Najlepsza odpowiedź również na 2019 rok;)
guillaumepotier

17

Mam to działające (= testowane) w IE8 +, najnowsze FF i chrome:

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

Klawisz ustawia ostrość przed kliknięciem (w przeciwnym razie chrome go ignoruje).

Uwaga: MUSISZ mieć wyświetlane i widoczne dane wejściowe (tak jak w, nie display:nonei nie visibility:hidden). Proponuję (jak wielu innych wcześniej), aby bezwzględnie ustawić wejście i wyrzucić je z ekranu.

#uploadInput {
    position: absolute;
    left: -9999px;
}

1
+1 za to. Zauważyłem również, że można ukryć otaczający element, ale nie przycisk wprowadzania pliku, a następnie pokazać otaczający element, wyostrzyć przycisk, aktywować go, a następnie ukryć przycisk.
Stevo

10

Sprawdź moje skrzypce.

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>


9

adardesign przyłapał go na ignorowaniu elementu wejściowego pliku, gdy jest on ukryty. Zauważyłem również, że wiele osób zmienia rozmiar elementu na 0 lub wypycha go poza granice za pomocą regulacji pozycjonowania i przepełnienia. To wszystko są świetne pomysły.
Alternatywnym sposobem, który wydaje się działać doskonale, jest po prostu ustawienie krycia na 0 . Wtedy zawsze możesz po prostu ustawić pozycję, aby nie przesuwać innych elementów, tak jak robi to hide. Przesunięcie elementu o prawie 10 000 pikseli w dowolnym kierunku wydaje się po prostu trochę niepotrzebne.

Oto mały przykład dla tych, którzy go chcą:

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);
}

7

Z ciekawości możesz zrobić coś takiego, jak chcesz, dynamicznie tworząc formularz przesyłania i plik wejściowy, bez dodawania ich do drzewa 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();
});

Nie ma potrzeby dodawania uploadForm do DOM.


1
DZIĘKUJĘ CI! Szukałem tego od 20 minut!
Labo,

5

Prawidłowy kod:

<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>


4

Właściwie znalazłem na to naprawdę prostą metodę:

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

W ten sposób twoje pole wejściowe pliku może mieć właściwość css wyświetlaną na none i nadal wygrywać transakcję :)


na wolniejszej maszynie może to być migotanie na ekranie. Nie jest to optymalne rozwiązanie
Dmitry Efimenko

4

Jest za późno na odpowiedź, ale myślę, że ta minimalna konfiguracja działa najlepiej. Ja też szukam tego samego.

  <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 przycisków wprowadzania pliku bootstrap


nigdy nie jest za późno na odpowiedź;)
AGuyCalledGerald

Kilka lat później nadal najlepsza odpowiedź IMO
DimmuR

4

To bardzo stara kwestia, ale niestety ta kwestia jest nadal aktualna i wymaga rozwiązania.

(Zaskakująco proste) rozwiązanie, które wymyśliłem, polega na „ukryciu” rzeczywistego pola wejściowego pliku i zawinięciu go w znacznik LABEL (może być oparty na Bootstrap i HTML5, w celu ulepszenia).

See here:Przykładowy kod tutaj

W ten sposób rzeczywiste pole wejściowe pliku jest niewidoczne, a wszystko, co widzisz, to dostosowany „przycisk”, który w rzeczywistości jest zmodyfikowanym elementem LABEL. Po kliknięciu tego elementu ETYKIETA pojawi się okno wyboru pliku, a wybrany plik przejdzie do pola wejściowego rzeczywistego pliku.

Ponadto możesz dowolnie manipulować wyglądem i zachowaniem (na przykład: pobrać nazwę wybranego pliku z pliku wejściowego pliku, po jego wybraniu i pokazać go gdzieś. Element LABEL nie robi tego automatycznie, oczywiście. Zwykle po prostu umieszczam go wewnątrz LABEL, jako jego treść tekstową).

Uważaj jednak! Manipulacja wyglądem i zachowaniem jest ograniczona do wszystkiego, co możesz sobie wyobrazić i o czym pomyśleć. ;-) ;-)


3

Udało mi się za pomocą prostego $ (...). Click (); z JQuery 1.6.1


1
Hmm ciekawy, jak to zrobiłeś, na mojej stronie (www.iscriptdesign.com) wykonując $ ('file: input'). Click () nic nie robi, ani $ ('file: input'). Trigger (' Kliknij');
dr jerry

Oto pełny przykład: <input type = "file" id = "picBrowse" ... a następnie $ ('# picBrowse'). Click ();
Valentin Galea

Testowałem na cr (nie wiem, która wersja) na Mac OS, działa jednak na FF 4 na XP. Dzięki!
dr jerry


2

miałem problemy z niestandardową walidacją po stronie klienta <input type="file"/>podczas używania fałszywego przycisku, aby go uruchomić, a rozwiązanie @Guillaume Bodi działało dla mnie (również opacity: 0;na Chrome)

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

i styl CSS do przesyłania danych

#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;
}

1

Spróbuj tego, to hack. pozycja: bezwzględna dotyczy przeglądarki Chrome, a wyzwalacz („zmiana”) dotyczy przeglądarki 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');
});

Zwróć na to uwagę $.browser jest przestarzały w nowszych wersjach jQuery
Kevin Beal

1

Mój problem był trochę inny na iOS 7. Okazuje się, że FastClick powodował problemy. Wszystko, co musiałem zrobić, to dodać class="needsclick"do mojego przycisku.


0

To prawdopodobnie najlepsza odpowiedź, biorąc pod uwagę problemy z różnymi przeglądarkami.

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">

0

Myślę, że rozumiem twój problem, bo mam podobny. Więc tag <label>ma atrybut dla, możesz użyć tego atrybutu, aby połączyć swoje wejście z type = "file". Ale jeśli nie chcesz aktywować tego za pomocą tej etykiety, ponieważ jakaś reguła twojego układu, możesz zrobić w ten sposób.

$(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>

Oczywiście dostosujesz to do własnego celu i układu, ale to jest łatwiejszy sposób, w jaki wiem, aby to działało !!


-1

Na podstawie odpowiedzi Guillaume Bodi zrobiłem to:

$('.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();
});

co oznacza, że ​​jest ukryty na początku, a następnie wyświetlany dla wyzwalacza, a następnie natychmiast ponownie ukryty.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.