Programowo uruchom okno dialogowe „wybierz plik”

100

Mam ukryty element wejściowy pliku. Czy możliwe jest wywołanie okna dialogowego wyboru pliku ze zdarzenia kliknięcia przycisku?

tamakisquare
źródło

Odpowiedzi:

146

Jeśli chcesz mieć własny przycisk do przesyłania pliku zamiast używania go <input type="file" />, możesz zrobić coś takiego:

<input id="myInput" type="file" style="visibility:hidden" />
<input type="button" value="Show Dialog" onclick="$('#myInput').click();" />

Zauważ, że użyłem visibility: hiddenzamiast display: none. Nie można wywołać zdarzenia kliknięcia w przypadku niewidocznego pliku wejściowego.

Mike Gwilt
źródło
Prosty w podstawowych przypadkach, ale nie jest kompatybilny z wieloma przeglądarkami. Należy pamiętać, że znacznie lepszym pomysłem jest połączenie tego rozwiązania z nałożeniem elementu wejściowego pliku na przycisk przy kryciu: 0, jak wspomniano w odpowiedzi Xeon06.
SquareCat
10
Aktualizacja: w nowoczesnych przeglądarkach możesz kliknąć wejście, którego nie ma nawet w DOM. Niesamowite!
Adria
7
Próbowałem tylko click()na display:nonewejściu i to działało
Daniel Cheung
15
Tak, tutaj w 2015 roku, click()żywioł z display: nonedziełami! ;) Jak wiele się zmieniło w ciągu ostatnich czterech lat.
ffxsam
Możesz hiddenzamiast tego użyć atrybutu style="visibility:hidden": <input id="myInput" type="file" hidden>( w3schools.com/tags/att_global_hidden.asp )
cespon
114

W większości odpowiedzi brakuje tu przydatnych informacji:

Tak, możesz programowo kliknąć element wejściowy za pomocą jQuery / JavaScript, ale tylko wtedy, gdy robisz to w module obsługi zdarzeń należącym do zdarzenia, które ZACZĘŁO UŻYTKOWNIK!

Na przykład nic się nie stanie, jeśli ty, skrypt, programowo klikniesz przycisk w wywołaniu zwrotnym Ajax, ale jeśli umieścisz tę samą linię kodu w module obsługi zdarzeń, który został wywołany przez użytkownika, zadziała.

PS debugger;Słowo kluczowe zakłóca okno przeglądarki, jeśli znajduje się przed programowym kliknięciem ... przynajmniej w chrome 33 ...

Fazi
źródło
jak słusznie wspomina @LouisBataillard: nie tylko oryginalny program obsługi zdarzeń musi być zainicjowany przez użytkownika; musi to być konkretnie zdarzenie kliknięcia. Oto skrzypce, które przedstawił, demonstrując to: link
Souhaieb Besbes
1
możesz kliknąć coś, co jest generowane dynamicznie. w jquery, czyli$(staticElementParent).on("click", "dynamicChild", function(){})
Daniel Cheung
1
DZIĘKUJĘ CI!!!! Testowałem wszystkie te odpowiedzi w konsoli javascript i oszalałem!
jdkealy
8
Przez pół godziny walczyłem z programowym monitowaniem o okno wprowadzania pliku. NIKT INNY stwierdził, że to niemożliwe, jeśli wydarzenie nie zostanie rozpoczęte przez użytkownika ... zasługujesz na dużo +1.
Umagon
1
Od Chrome 62 debugger;słowo kluczowe nie zakłóca już automatycznego klikania
Chris W.,
62

Dla przypomnienia, istnieje alternatywne rozwiązanie, które nie wymaga javascript. To trochę hack, wykorzystując fakt, że kliknięcie etykiety powoduje skupienie się na powiązanych danych wejściowych.

Potrzebujesz a <label>z odpowiednim foratrybutem (wskazuje na wejście), opcjonalnie stylizowanym na przycisk (z bootstrapem, użyj btn btn-default). Gdy użytkownik kliknie etykietę, zostanie otwarte okno dialogowe, na przykład:

<!-- optionnal, to add a bit of style -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>

<!-- minimal setup -->
<label for="exampleInput" class="btn btn-default">
  Click me
</label>
<input type="file" id="exampleInput" style="display: none" />

m_x
źródło
2
Podoba mi się ten, nie chcę włączać pełnego jQuery do mojego projektu Angulara, działa dobrze :)
Starscream1984
1
czy to zachowanie jest niezawodne we wszystkich nowoczesnych przeglądarkach?
JoshuaDavid,
Działa to bez żadnego JS, używając natywnego zachowania przeglądarki. W połączeniu ze zdarzeniami onDrop implementacja bogatego w funkcje przesyłania plików działa świetnie!
Yanick Rochon
Musiałem majstrować przy CSS, ale potem zadziałało - mianowicie widoczność pliku wejściowego z "display: none" nie jest w porządku we wszystkich przeglądarkach. (Ale krycie
równe
13

Nie jestem pewien, jak przeglądarki radzą sobie z kliknięciami type="file"elementów (względy bezpieczeństwa i wszystko inne), ale to powinno działać:

$('input[type="file"]').click();

Przetestowałem to JSFiddle w Chrome, Firefox i Opera i wszystkie pokazują okno dialogowe przeglądania plików.

Bojangles
źródło
5
Wydaje się, że działa to tylko wtedy, gdy zdarzenie „dzwonienie” samo jest zdarzeniem kliknięcia. Na przykład wydaje się, że nie można otworzyć okna dialogowego pliku na podstawie hoverzdarzenia: jsfiddle.net/UQfaZ/1
Louis B.
Czy wiesz, jak można to przetestować za pomocą Selenium, jeśli wejście nie znajduje się w DOM?
Sebastien Lorber
4

Zawijam input[type=file]etykietę, stylizuję ją labelwedług własnych upodobań i ukrywam input.

<label class="btn btn-default fileLabel" data-toggle="tooltip" data-placement="top" title="Upload">
    <input type="file">
    <span><i class="fa fa-upload"></i></span>
</label>

<style>
    .fileLabel input[type="file"] {
        position: fixed;
        top: -1000px;
    }
</style>

Rozwiązanie czysto CSS.

Ponyboy
źródło
Po prostu ustaw, <input type="file" hidden>aby usunąć potrzebę stosowania stylu CSS.
Sylvain Lesage
3

Niestety, jedynym sposobem jest utworzenie <input type="file">elementu, a następnie zasymulowanie kliknięcia.

Jest mała wtyczka (bezwstydna wtyczka), która wyeliminuje ból związany z koniecznością robienia tego przez cały czas: file-dialog

fileDialog()
    .then(file => {
        const data = new FormData()
        data.append('file', file[0])
        data.append('imageName', 'flower')

        // Post to server
        fetch('/uploadImage', {
            method: 'POST',
            body: data
        })
    })
Alister
źródło
3

Najlepsze rozwiązanie, działa we wszystkich przeglądarkach ... nawet na urządzeniach mobilnych.

<div class="btn" id="s_photo">Upload</div>

<input type="file" name="s_file" id="s_file" style="opacity: 0;">';

<!--jquery-->

<script>
    $("#s_photo").click(function() {
        $("#s_file").trigger("click");
    });
</script>

Ukrywanie typu pliku wejściowego powoduje problemy z przeglądarkami, krycie jest najlepszym rozwiązaniem, ponieważ nie jest ukrywany, po prostu się nie wyświetla. :)

Pessa
źródło
1
powinieneś wspomnieć, że wymaga to odwołania do jQuery.
Brino
Nieprzezroczystość wiąże się z zupełnie niepowiązaną koncepcją - masz po prostu szczęście, jeśli nie wpływa na Twój układ z elementem „przezroczystym”. Element powinien tam być, ale niewidoczny, więc visibility:hiddenpowinien być lepszym wyborem.
conny
visibility: hiddennadal wpływa na układ. display: nonejest tym, czego chcesz.
stommestack
1

Ze względów bezpieczeństwa nie można tego zrobić w różnych przeglądarkach. To, co zwykle robią ludzie, to nakładanie pliku wejściowego na coś innego i ustawianie jego widoczności na ukrytą, aby był uruchamiany samodzielnie. Więcej informacji tutaj.

Alex Turpin
źródło
2
OP mówi <input type="file">, a nie <select>.
Bojangles
Żaden problem. Sam to robiłem wcześniej. W odpowiedzi na Twoją zmianę jest na to sposób; wyzwalając zdarzenie click elementu za pomocą jQuery $.click().
Bojangles
1
@JamWaffles okay, to dziwne. Wyraźnie pamiętam, że kilka tygodni temu spędziłem nad tym cały dzień. To nie działało w Firefox i IE. Ciekawe, o co chodziło ...
Alex Turpin,
Ciekawy. W mojej odpowiedzi mam JSFiddle, który działa z FF. Nie mogę testować w IE (jestem na Linuksie), więc nie wiem, czy to nadal będzie wymiotować.
Bojangles
2
Dobry wysiłek badawczy! Gdybym wziął ani grosza za każdym razem, gdy twórcy stron internetowych musieli włamać się do jakiegoś całkiem normalnego zachowania, byłbym obrzydliwie bogaty.
Bojangles
1

Upewnij się, że używasz wiązania, aby uzyskać właściwości komponentów w REACT

class FileUploader extends Component {
  constructor (props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
   onChange=(e,props)=>{
    const files = e.target.files;
    const selectedFile = files[0];
    ProcessFileUpload(selectedFile,props.ProgressCallBack,props.ErrorCallBack,props.CompleatedCallBack,props.BaseURL,props.Location,props.FilesAllowed);
  }
   handleClick = () => {
    this.refs.fileUploader.click();
  }
  render()
  {
  return(
      <div>
        <button type="button" onClick={this.handleClick}>Select File</button>  
        <input type='file' onChange={(e)=>this.onChange(e,this.props)} ref="fileUploader" style={{display:"none"}} />
      </div>)
  }
}
m-farhan
źródło
0

Korzystając z jQuery, możesz wywołać click()symulację kliknięcia.

pdubs
źródło
0

To zadziałało dla mnie:

$('#fileInput').val('');
dileepar
źródło
0

Dla tych, którzy chcą tego samego, ale używają React

openFileInput = () => {
    this.fileInput.click()
}

<a href="#" onClick={this.openFileInput}>
    <p>Carregue sua foto de perfil</p>
    <img src={img} />
</a>
<input style={{display:'none'}} ref={(input) => { this.fileInput = input; }} type="file"/>
Vinicius Lima
źródło
0
<div id="uploadButton">UPLOAD</div>
<form action="[FILE_HANDLER_URL]" style="display:none">
     <input id="myInput" type="file" />
</form>
<script>
  const uploadButton = document.getElementById('uploadButton');
  const myInput = document.getElementById('myInput');

  uploadButton.addEventListener('click', () => {
    myInput.click();
  });
</script>
yairniz
źródło