Activar programáticamente el cuadro de diálogo "seleccionar archivo"

99

Tengo un elemento de entrada de archivo oculto. ¿Es posible activar su cuadro de diálogo de selección de archivo desde el evento de clic de un botón?

tamakisquare
fuente

Respuestas:

146

Si está buscando tener su propio botón para cargar un archivo en lugar de usarlo <input type="file" />, puede hacer algo como:

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

Tenga en cuenta que usé visibility: hidden, en lugar de display: none. No puede llamar al evento de clic en una entrada de archivo no mostrada.

Mike Gwilt
fuente
Sencillo para casos básicos, pero no compatible con muchos navegadores. Tenga en cuenta que es una idea mucho mejor combinar esta solución superponiendo el elemento de entrada del archivo sobre un botón en opacidad: 0, como se ha mencionado en la respuesta de Xeon06.
SquareCat
10
Actualización: en los navegadores modernos, puede hacer clic en una entrada que ni siquiera está en el DOM. ¡Increíble!
Adria
7
Acabo de probar click()una display:noneentrada y funcionó
Daniel Cheung
15
Sí, aquí en el año 2015, ¡ click()en un elemento con display: noneobras! ;) Cómo han cambiado las cosas en los últimos cuatro años.
ffxsam
Puede usar el hiddenatributo en su lugar style="visibility:hidden": <input id="myInput" type="file" hidden>( w3schools.com/tags/att_global_hidden.asp )
cespon
113

La mayoría de las respuestas aquí carecen de información útil:

Sí, puede hacer clic mediante programación en el elemento de entrada usando jQuery / JavaScript, pero solo si lo hace en un controlador de eventos que pertenece a un evento QUE FUE INICIADO POR EL USUARIO.

Entonces, por ejemplo, no sucederá nada si usted, el script, hace clic programáticamente en el botón en una devolución de llamada ajax, pero si coloca la misma línea de código en un controlador de eventos que fue generado por el usuario, funcionará.

PD: la debugger;palabra clave interrumpe la ventana de exploración si está antes del clic programático ... al menos en Chrome 33 ...

Fazi
fuente
como @LouisBataillard menciona con razón: no solo el usuario debe iniciar el controlador de eventos original; debe ser específicamente un evento de clic. Aquí hay un violín que proporcionó demostrando esto: enlace
Souhaieb Besbes
1
puede hacer clic en algo que se genera dinámicamente. en jquery, es decir$(staticElementParent).on("click", "dynamicChild", function(){})
Daniel Cheung
1
¡¡¡¡GRACIAS!!!! ¡He estado probando todas estas respuestas en la consola de JavaScript y me he vuelto loco!
jdkealy
8
He estado luchando durante media hora con la solicitud programática de una ventana de entrada de archivos. NADIE MÁS declaró que es imposible si el evento no es iniciado por el usuario ... te mereces mucho +1.
Umagon
1
A partir de Chrome 62, la debugger;palabra clave ya no interrumpe el clic programático
Chris W.
62

Solo para el registro, existe una solución alternativa que no requiere javascript. Es un truco, explotar el hecho de que al hacer clic en una etiqueta, el foco se centra en la entrada asociada.

Necesita un atributo <label>adecuado for(apunta a la entrada), opcionalmente con el estilo de un botón (con bootstrap, use btn btn-default). Cuando el usuario hace clic en la etiqueta, se abre el cuadro de diálogo, ejemplo:

<!-- 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
fuente
2
Me gusta este, no quiero incluir jQuery completo en mi proyecto Angular, funciona bien :)
Starscream1984
1
¿Es este comportamiento confiable en todos los navegadores modernos?
JoshuaDavid
Esto funciona sin JS en absoluto, utilizando el comportamiento del navegador nativo. Junto con los eventos onDrop, ¡la implementación de una carga de archivos rica en funciones funciona muy bien!
Yanick Rochon
Tuve que jugar con el CSS pero luego funcionó, es decir, la visibilidad de entrada del archivo que tiene "display: none" no está bien en todos los navegadores. (Pero se puede usar opacidad de 0, etc.)
driftcatcher
13

No estoy seguro de cómo los navegadores manejan los clics en los type="file"elementos (preocupaciones de seguridad y todo), pero esto debería funcionar:

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

He probado este jsFiddle en Chrome, Firefox y Opera, y todos ellos se observa el cuadro de diálogo de exploración de archivos.

Bojangles
fuente
5
Esto parece funcionar sólo cuando el evento de "llamada" es en sí mismo un evento de clic. Por ejemplo, no parece posible abrir el cuadro de diálogo del archivo según un hoverevento: jsfiddle.net/UQfaZ/1
Louis B.
¿Sabes cómo se puede probar esto con Selenium si la entrada no está en el DOM?
Sebastien Lorber
4

Lo envuelvo input[type=file]en una etiqueta, luego le doy un estilo labela su gusto y lo oculto 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>

Solución puramente CSS.

Ponyboy
fuente
Simplemente configúrelo <input type="file" hidden>para eliminar la necesidad de aplicar un estilo CSS.
Sylvain Lesage
3

De forma nativa, la única forma es crear un <input type="file"> elemento y luego simular un clic, desafortunadamente.

Hay un pequeño complemento (enchufe desvergonzado) que eliminará el dolor de tener que hacer esto todo el tiempo: 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
fuente
3

La mejor solución, funciona en todos los navegadores ... incluso en el móvil.

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

Ocultar el tipo de archivo de entrada causa problemas con los navegadores, la opacidad es la mejor solución porque no se oculta, simplemente no se muestra. :)

Pessa
fuente
1
debe mencionar que esto requiere una referencia de jquery.
Brino
La opacidad implica un concepto totalmente ajeno: tiene suerte si no afecta su diseño con un elemento "transparente". El elemento debería estar ahí, pero no visible, por lo que visibility:hiddendebería ser una mejor opción.
conny
visibility: hiddentodavía afecta el diseño. display: nonees lo que quieres.
stommestack
1

No existe una forma de hacerlo en varios navegadores, por razones de seguridad. Lo que la gente suele hacer es superponer el archivo de entrada sobre otra cosa y configurar su visibilidad como oculta para que se active por sí solo. Más info aquí.

Alex Turpin
fuente
2
El OP está hablando <input type="file">, no <select>.
Bojangles
No es un problema. Lo he hecho yo mismo antes. En respuesta a tu edición, no es una manera de hacerlo; activando el evento click del elemento con jQuery $.click().
Bojangles
1
@JamWaffles está bien, eso es extraño. Recuerdo claramente que pasé un día entero en esto hace unas semanas. No funcionó en Firefox e IE justamente. Me pregunto cuál fue el trato ...
Alex Turpin
Curioso. Tengo un JSFiddle en mi respuesta que funciona con FF. No puedo probar en IE (estoy en Linux), así que no sé si eso seguirá vomitando.
Bojangles
2
¡Buen esfuerzo de investigación allí! Si gastara un centavo por cada vez que los desarrolladores web tuvieran que modificar un comportamiento bastante normal en algo, sería muy rico.
Bojangles
1

Asegúrese de que está utilizando el enlace para obtener los accesorios de los componentes en 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
fuente
0

Usando jQuery puede llamar click()para simular un clic.

pdubs
fuente
0

Esto funcionó para mí:

$('#fileInput').val('');
dileepar
fuente
0

Para aquellos que quieren lo mismo pero están usando 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
fuente
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
fuente