Déclenchez par programme la boîte de dialogue «Sélectionner un fichier»

100

J'ai un élément d'entrée de fichier caché. Est-il possible de déclencher sa boîte de dialogue de sélection de fichier à partir d'un événement de clic sur un bouton?

tamakisquare
la source

Réponses:

146

Si vous cherchez à avoir votre propre bouton pour télécharger un fichier au lieu d'utiliser <input type="file" />, vous pouvez faire quelque chose comme:

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

Notez que j'ai utilisé visibility: hidden, au lieu de display: none. Vous ne pouvez pas appeler l'événement de clic sur une entrée de fichier non affichée.

Mike Gwilt
la source
Simple pour les cas de base, mais non compatible avec de nombreux navigateurs. Veuillez noter que c'est une bien meilleure idée de combiner cette solution avec la superposition de l'élément d'entrée du fichier sur un bouton à opacity: 0, comme cela a été mentionné dans la réponse de Xeon06.
SquareCat
10
Mise à jour: dans les navigateurs modernes, vous pouvez cliquer sur une entrée qui ne se trouve même pas dans le DOM. Impressionnant!
Adria
7
Je viens d'essayer click()une display:noneentrée et cela a fonctionné
Daniel Cheung
15
Oui, ici en 2015, click()sur un élément avec des display: noneoeuvres! ;) Comment les choses ont changé au cours des quatre dernières années.
ffxsam
Vous pouvez utiliser l' hiddenattribut à la place style="visibility:hidden": <input id="myInput" type="file" hidden>( w3schools.com/tags/att_global_hidden.asp )
cespon
114

La plupart des réponses ici manquent d'informations utiles:

Oui, vous pouvez cliquer par programme sur l'élément d'entrée à l'aide de jQuery / JavaScript, mais uniquement si vous le faites dans un gestionnaire d'événements appartenant à un événement QUI A ÉTÉ DÉMARRÉ PAR L'UTILISATEUR!

Ainsi, par exemple, rien ne se passera si vous, le script, cliquez par programme sur le bouton dans un rappel ajax, mais si vous mettez la même ligne de code dans un gestionnaire d'événements qui a été déclenché par l'utilisateur, cela fonctionnera.

PS Le debugger;mot-clé perturbe la fenêtre de navigation si c'est avant le clic programmatique ... au moins en chrome 33 ...

Fazi
la source
comme @LouisBataillard le mentionne à juste titre: non seulement le gestionnaire d'événements d'origine doit être initié par l'utilisateur; il doit s'agir spécifiquement d'un événement de clic. Voici un violon qu'il a fourni pour démontrer ceci: lien
Souhaieb Besbes
1
vous pouvez cliquer sur quelque chose qui est généré dynamiquement. dans jquery, c'est-à-dire$(staticElementParent).on("click", "dynamicChild", function(){})
Daniel Cheung
1
MERCI!!!! J'ai testé toutes ces réponses dans la console javascript et je suis devenu fou!
jdkealy
8
Cela fait une demi-heure que je lutte pour ouvrir une fenêtre de saisie de fichier par programmation. PERSONNE D'AUTRE a déclaré qu'il est impossible si l'événement n'est pas démarré par l'utilisateur ... vous méritez beaucoup de +1.
Umagon
1
À partir de Chrome 62, le debugger;mot - clé ne perturbe plus le clic programmatique
Chris W.
62

Pour mémoire, il existe une solution alternative qui ne nécessite pas de Javascript. C'est un peu un hack, exploitant le fait que cliquer sur une étiquette met l'accent sur l'entrée associée.

Vous avez besoin d'un <label>avec un forattribut approprié (pointe vers l'entrée), optionnellement stylé comme un bouton (avec bootstrap, utilisez btn btn-default). Lorsque l'utilisateur clique sur l'étiquette, la boîte de dialogue s'ouvre, exemple:

<!-- 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
la source
2
J'aime celui-ci, je ne veux pas inclure jQuery complet dans mon projet Angular, fonctionne bien :)
Starscream1984
1
ce comportement est-il fiable dans tous les navigateurs modernes?
JoshuaDavid
Cela fonctionne sans aucun JS, en utilisant le comportement natif du navigateur. Associé aux événements onDrop, l'implémentation d'un téléchargement de fichiers riche en fonctionnalités fonctionne très bien!
Yanick Rochon
J'ai dû jouer avec le CSS mais cela a fonctionné - à savoir la visibilité d'entrée du fichier ayant "display: none" n'est pas correcte dans tous les navigateurs. (Mais une opacité de 0, etc. peut être utilisée)
driftcatcher
13

Je ne sais pas comment les navigateurs gèrent les clics sur les type="file"éléments (problèmes de sécurité et tout), mais cela devrait fonctionner:

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

J'ai testé ce JSFiddle dans Chrome, Firefox et Opera et ils affichent tous la boîte de dialogue de navigation de fichiers.

Bojangles
la source
5
Cela semble fonctionner uniquement lorsque l'événement "appelant" est lui-même un événement de clic. Par exemple, il ne semble pas possible d'ouvrir la boîte de dialogue de fichier basée sur un hoverévénement: jsfiddle.net/UQfaZ/1
Louis B.
Savez-vous comment cela peut être testé avec Selenium si l'entrée n'est pas dans le DOM?
Sebastien Lorber
4

J'emballe le input[type=file]dans une étiquette d'étiquette, puis je le stylise labelà votre guise et masque le 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>

Solution purement CSS.

Garçon poney
la source
Il suffit de régler <input type="file" hidden>pour supprimer le besoin d'appliquer un style CSS.
Sylvain Lesage
3

Nativement, le seul moyen est de créer un <input type="file"> élément puis de simuler un clic, malheureusement.

Il y a un petit plugin (plug sans vergogne) qui vous évitera d'avoir à faire cela tout le temps: 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
la source
3

La meilleure solution, fonctionne dans tous les navigateurs .. même sur mobile.

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

Le masquage du type de fichier d'entrée pose des problèmes avec les navigateurs, l'opacité est la meilleure solution car elle ne se cache pas, mais ne s'affiche pas. :)

Pessa
la source
1
vous devez mentionner que cela nécessite une référence jquery.
Brino
L'opacité implique un concept totalement indépendant - vous avez simplement de la chance si cela n'affecte pas votre mise en page avec un élément "transparent". L'élément devrait être là, mais pas visible, donc visibility:hiddendevrait être un meilleur choix.
conny le
visibility: hiddenaffecte toujours la mise en page. display: noneest ce que vous voulez.
stommestack
1

Il n'y a pas de moyen de le faire entre navigateurs, pour des raisons de sécurité. Ce que les gens font généralement, c'est superposer le fichier d'entrée sur quelque chose d'autre et définir sa visibilité sur masqué afin qu'il soit déclenché par lui-même. Plus d'infos ici.

Alex Turpin
la source
2
Le PO parle <input type="file">, non <select>.
Bojangles
Pas de problème. Je l'ai déjà fait moi-même. En réponse à votre modification, il existe un moyen de le faire; en déclenchant l'événement click de l'élément avec jQuery $.click().
Bojangles
1
@JamWaffles ok c'est bizarre. Je me souviens clairement avoir passé une journée entière là-dessus il y a quelques semaines. Cela n'a pas fonctionné dans Firefox et IE afair. Je me demande ce qu'était l'accord ...
Alex Turpin
Curieuse. J'ai un JSFiddle dans ma réponse qui fonctionne avec FF. Je ne peux pas tester dans IE (je suis sous Linux), donc je ne sais pas si cela va encore vomir.
Bojangles
2
Bon effort de recherche là-bas! Si je dépense un sou pour chaque fois que les développeurs Web doivent pirater un comportement assez normal en quelque chose, je serais très riche.
Bojangles
1

Assurez-vous que vous utilisez la liaison pour obtenir les accessoires de composant dans 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
la source
0

En utilisant jQuery, vous pouvez appeler click()pour simuler un clic.

pdubs
la source
0

Cela a fonctionné pour moi:

$('#fileInput').val('');
dileepar
la source
0

Pour ceux qui veulent la même chose mais utilisent 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
la source
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
la source