116
$('#id').click();

It doesn't work on Chrome 26 on Mac OS.

The problem actually is creation "upload" widget that can be integrated in a form. Widget will consists of two parts. The first part is div with initiator button and error/success messages. I think the way is put another form as the second part with file input and submit file into the iframe. After submition we fill hidden field in first part in main form or show errors in the same.

Easy way is adding file-form into main-form, but it's prohibited.

domsson
  • 4,553
  • 2
  • 22
  • 40
Luciuz
  • 1,637
  • 5
  • 14
  • 15

10 Answers10

249

JS only - no need for jquery

Simply create an input element and trigger the click.

var input = document.createElement('input');
input.type = 'file';
input.click();

This is the most basic, pop a select-a-file dialog, but its no use for anything without handling the selected file...

Handling the files

Adding an onchange event to the newly created input would allow us to do stuff once the user has selected the file.

var input = document.createElement('input');
input.type = 'file';

input.onchange = e => { 
   var file = e.target.files[0]; 
}

input.click();

At the moment we have the file variable storing various information :

file.name // the file's name including extension
file.size // the size in bytes
file.type // file type ex. 'application/pdf'

Great!

But, what if we need the content of the file?

In order to get to the actual content of the file, for various reasons. place an image, load into canvas, create a window with Base64 data url, etc. we would need to use the FileReader API

We would create an instance of the FileReader, and load our user selected file reference to it.

var input = document.createElement('input');
input.type = 'file';

input.onchange = e => { 

   // getting a hold of the file reference
   var file = e.target.files[0]; 

   // setting up the reader
   var reader = new FileReader();
   reader.readAsText(file,'UTF-8');

   // here we tell the reader what to do when it's done reading...
   reader.onload = readerEvent => {
      var content = readerEvent.target.result; // this is the content!
      console.log( content );
   }

}

input.click();

Trying pasting the above code into your devtool's console window, it should produce a select-a-file dialog, after selecting the file, the console should now print the contents of the file.

Example - "Stackoverflow's new background image!"

Let's try to create a file select dialog to change stackoverflows background image to something more spicy...

var input = document.createElement('input');
input.type = 'file';

input.onchange = e => { 

   // getting a hold of the file reference
   var file = e.target.files[0]; 

   // setting up the reader
   var reader = new FileReader();
   reader.readAsDataURL(file); // this is reading as data url

   // here we tell the reader what to do when it's done reading...
   reader.onload = readerEvent => {
      var content = readerEvent.target.result; // this is the content!
      document.querySelector('#content').style.backgroundImage = 'url('+ content +')';
   }

}

input.click();

open devtools, and paste the above code into console window, this should pop a select-a-file dialog, upon selecting an image, stackoverflows content box background should change to the image selected.

starball
  • 20,030
  • 7
  • 43
  • 238
  • 3
    While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – kayess Dec 05 '16 at 10:47
  • 4
    Excellent. But i had troubles to get this working on Safari iOS. The onchange event didnt trigger. – bitrevolution Aug 23 '17 at 10:46
  • 1
    See here for how to access the file: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications `document.getElementById('input').files[0];` – cmann Sep 15 '17 at 07:05
  • 11
    When I used the proposed code, I got the following error: `File chooser dialog can only be shown with a user activation.` How can I solve this problem? – Paul Apr 03 '20 at 11:13
  • 1
    @Paul `File chooser dialog can only be shown with a user activation.` Basically, that means it will only open if a user clicked something. Try something like this: `document.body.onclick = openFileFunction`. When you click the webpage, it should now open properly. – luek baja Dec 05 '20 at 19:16
  • Verry nice answer – Squirrel in training Jun 23 '22 at 11:31
  • Absolute hero! Exactly what I was searching for desperately – derHugo Nov 09 '22 at 12:07
191

Using jQuery

I would create a button and an invisible input like so:

<button id="button">Open</button>
<input id="file-input" type="file" name="name" style="display: none;" />

and add some jQuery to trigger it:

$('#button').on('click', function() {
    $('#file-input').trigger('click');
});

Using Vanilla JS

Same idea, without jQuery (credits to @Pascale):

<button onclick="document.getElementById('file-input').click();">Open</button>
<input id="file-input" type="file" name="name" style="display: none;" />
Ron van der Heijden
  • 14,803
  • 7
  • 58
  • 82
  • 3
    It's much, much more elegant solution than making the input field transparent – Aron Lorincz Jul 02 '15 at 06:23
  • I used the same technique (in pure js: form.file_selector.click();) where file_selector is a dynamically added file input (added by innerHTML). but it does not work. Any help or suggestions please? – fekiri malek Aug 02 '16 at 13:26
  • 1
    @Ron van der Heijden thank you i think i figured out why it was not working (now it's working anyway). For those that may have similar issue may be the cause if that for security reasons the event does not fire unless it's called after user event (click or so). i was tying to fire the event just after (inside a function of) an ajax request. – fekiri malek Aug 05 '16 at 23:01
  • 1
    Thanks a lot for the Vanilla JS example! – Jobsamuel Jun 06 '17 at 16:36
  • The vanilla js solution is perfect for me. Thank you very much. – JackTools.Net Dec 09 '17 at 07:14
  • 1
    How can I get selected folder path ?? – eomer Jul 29 '19 at 09:15
  • It's better to use ```opacity: 0``` to hide the file input instead of visibility: hidden or display: none, because assistive technology interprets the latter two styles to mean the file input isn't interactive. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file – Arman May 30 '22 at 20:12
28

Ready-to-use function (using Promise)

/**
 * Select file(s).
 * @param {String} contentType The content type of files you wish to select. For instance, use "image/*" to select all types of images.
 * @param {Boolean} multiple Indicates if the user can select multiple files.
 * @returns {Promise<File|File[]>} A promise of a file or array of files in case the multiple parameter is true.
 */
function selectFile(contentType, multiple){
    return new Promise(resolve => {
        let input = document.createElement('input');
        input.type = 'file';
        input.multiple = multiple;
        input.accept = contentType;

        input.onchange = () => {
            let files = Array.from(input.files);
            if (multiple)
                resolve(files);
            else
                resolve(files[0]);
        };

        input.click();
    });
}

Try it here

// Content wrapper element
let contentElement = document.getElementById("content");

// Button callback
async function onButtonClicked(){
    let files = await selectFile("image/*", true);
    contentElement.innerHTML = files.map(file => `<img src="${URL.createObjectURL(file)}" style="width: 100px; height: 100px;">`).join('');
}

// ---- function definition ----
function selectFile (contentType, multiple){
    return new Promise(resolve => {
        let input = document.createElement('input');
        input.type = 'file';
        input.multiple = multiple;
        input.accept = contentType;

        input.onchange = _ => {
            let files = Array.from(input.files);
            if (multiple)
                resolve(files);
            else
                resolve(files[0]);
        };

        input.click();
    });
}
<button onclick="onButtonClicked()">Select images</button>
<div id="content"></div>
Yairopro
  • 9,084
  • 6
  • 44
  • 51
14

In HTML only:

<label>
  <input type="file" name="input-name" style="display: none;" />
  <span>Select file</span>
</label>

Check this fiddle with the code above.

nunocastromartins
  • 577
  • 1
  • 5
  • 11
14

For the sake of completeness, Ron van der Heijden's solution in pure JavaScript:

<button onclick="document.querySelector('.inputFile').click();">Select File ...</button>
<input class="inputFile" type="file" style="display: none;">
Community
  • 1
  • 1
Pascale
  • 311
  • 2
  • 4
  • 11
10

To expand on the answer from 'levi' and to show how to get the response from the upload so you can process the file upload:

selectFile(event) {
    event.preventDefault();

    file_input = document.createElement('input');
    file_input.addEventListener("change", uploadFile, false);
    file_input.type = 'file';
    file_input.click();
},

uploadFile() {
    let dataArray = new FormData();
    dataArray.append('file', file_input.files[0]);

    // Obviously, you can substitute with JQuery or whatever
    axios.post('/your_super_special_url', dataArray).then(function() {
        //
    });
}
Robert Kehoe
  • 421
  • 5
  • 7
7

function promptFile(contentType, multiple) {
  var input = document.createElement("input");
  input.type = "file";
  input.multiple = multiple;
  input.accept = contentType;
  return new Promise(function(resolve) {
    document.activeElement.onfocus = function() {
      document.activeElement.onfocus = null;
      setTimeout(resolve, 500);
    };
    input.onchange = function() {
      var files = Array.from(input.files);
      if (multiple)
        return resolve(files);
      resolve(files[0]);
    };
    input.click();
  });
}
function promptFilename() {
  promptFile().then(function(file) {
    document.querySelector("span").innerText = file && file.name || "no file selected";
  });
}
<button onclick="promptFilename()">Open</button>
<span></span>
1

First Declare a variable to store filenames (to use them later):

var myfiles = [];

Open File Dialog

$('#browseBtn').click(function() {
    $('<input type="file" multiple>').on('change', function () {
        myfiles = this.files; //save selected files to the array
        console.log(myfiles); //show them on console
    }).click();
});

i'm posting it, so it may help someone because there are no clear instructions on the internet to how to store filenames into an array!

Hassaan Raza
  • 91
  • 1
  • 11
0

With jquery library

<button onclick="$('.inputFile').click();">Select File ...</button>
<input class="inputFile" type="file" style="display: none;">
Arcanjo ZN
  • 11
  • 1
  • Hello! While this code may solve the question, [including an explanation](https://meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Brian61354270 Apr 21 '20 at 00:37
0

This problem puzzled me. Adding addeventlistener invoked the event which was something I didn't want. If you're interest is in a simple chooser, events aren't required. the input/file dialog will return from the separate window to the caller with the selected filename (if you look at the element in a debugger the "files" object also carries some other attributes. Thank you user4602228 for pointing the way...

Simple in/out file selector shown below >>>

function loadsettings()
//
// use web page dialog to get user settings file
//
{
   var setload=parent.settings.document.createElement("input");
   setload.type="file";
   setload.click();
   settings(*setload.files[0]*,false,false); //these are custom parameters 
}
return;