58

Is there any way to open the browse for files dialog box when a <a href> link is clicked using javascript? It should function like a normal browse for files button and give the names/list of files selected in response.

Click Upvote
  • 235,452
  • 251
  • 553
  • 736

9 Answers9

68

Here is a non-jQuery solution. Note you can't just use .click() as some browsers do not support it.

<script type="text/javascript">
function performClick(elemId) {
   var elem = document.getElementById(elemId);
   if(elem && document.createEvent) {
      var evt = document.createEvent("MouseEvents");
      evt.initEvent("click", true, false);
      elem.dispatchEvent(evt);
   }
}
</script>
<a href="#" onclick="performClick('theFile');">Open file dialog</a>
<input type="file" id="theFile" />
skia.heliou
  • 1,388
  • 2
  • 16
  • 28
Samuel Liew
  • 68,352
  • 105
  • 140
  • 225
  • 1
    Its important to note that if you do this, and then use javascript to submit the form e.g. form.submit() you will get an access is denied error – nuander Jun 01 '12 at 15:57
  • 34
    (2013) you can use `.click()` all modern browsers (including ie10) support `.click()` method http://jsfiddle.net/vnYVB/ . Don't use `display:none` on `input type:file` because this won't work on safari. To fix this safari problem you should use `position:fixed;top:-1000` to hide the `input type:file`. (I know this is old but this post is ranking high at search engines and may mislead passer bys) – Jo E. Aug 01 '13 at 11:35
  • am I wrong or it should be `elem.dispatchEvent(...)` instead of `node.dispatchEvent(...)` – Richard Hutta Jan 12 '15 at 13:41
  • 5
    Encase anyone else is having this issue, it seems that at least some browsers/OSes require a user-initiated event to be in the call-stack for it to fire. So calling it manually (or even in the console) won't work. – Fewfre Jun 03 '15 at 15:45
23

Use this.

<script>
  function openFileOption()
{
  document.getElementById("file1").click();
}
</script>
     <input type="file" id="file1" style="display:none">
     <a href="#" onclick="openFileOption();return;">open File Dialog</a>
birendra
  • 239
  • 2
  • 2
  • `display: none` seems to not work on Safari. Maybe you should put it into a div with `overflow: hidden;` and set `position: relative; top: -1000px` on the input ? – Zachary Dahan Sep 17 '15 at 11:24
20

Create input element.

Missing from these answers is how to get a file dialog without a input element on the page.

The function to show the input file dialog.

function openFileDialog (accept, callback) {  // this function must be called from  a user
                                              // activation event (ie an onclick event)
    
    // Create an input element
    var inputElement = document.createElement("input");

    // Set its type to file
    inputElement.type = "file";

    // Set accept to the file types you want the user to select. 
    // Include both the file extension and the mime type
    inputElement.accept = accept;

    // set onchange event to call callback when user has selected file
    inputElement.addEventListener("change", callback)
    
    // dispatch a click event to open the file dialog
    inputElement.dispatchEvent(new MouseEvent("click")); 
}

NOTE the function must be part of a user activation such as a click event. Attempting to open the file dialog without user activation will fail.

NOTE input.accept is not used in Edge

Example.

Calling above function when user clicks an anchor element.

// wait for window to load
window.addEventListener("load", windowLoad);

// open a dialog function
function openFileDialog (accept, multy = false, callback) { 
    var inputElement = document.createElement("input");
    inputElement.type = "file";
    inputElement.accept = accept; // Note Edge does not support this attribute
    if (multy) {
        inputElement.multiple = multy;
    }
    if (typeof callback === "function") {
         inputElement.addEventListener("change", callback);
    }
    inputElement.dispatchEvent(new MouseEvent("click")); 
}

// onload event
function windowLoad () {
    // add user click event to userbutton
    userButton.addEventListener("click", openDialogClick);
}

// userButton click event
function openDialogClick () {
    // open file dialog for text files
    openFileDialog(".txt,text/plain", true, fileDialogChanged);
}

// file dialog onchange event handler
function fileDialogChanged (event) {
    [...this.files].forEach(file => {
        var div = document.createElement("div");
        div.className = "fileList common";
        div.textContent = file.name;
        userSelectedFiles.appendChild(div);
    });
}
.common {
    font-family: sans-serif;
    padding: 2px;
    margin : 2px;
    border-radius: 4px;
 }
.fileList {
    background: #229;
    color: white;
}
#userButton {
    background: #999;
    color: #000;
    width: 8em;
    text-align: center;
    cursor: pointer;
}

#userButton:hover {
   background : #4A4;
   color : white;
}
<a id = "userButton" class = "common" title = "Click to open file selection dialog">Open file dialog</a>
<div id = "userSelectedFiles" class = "common"></div>

Warning the above snippet is written in ES6.

Community
  • 1
  • 1
Blindman67
  • 41,565
  • 7
  • 47
  • 102
14

Unfortunately, there isn't a good way to browse for files with a JavaScript API. Fortunately, it's easy to create a file input in JavaScript, bind an event handler to its change event, and simulate a user clicking on it. We can do this without modifications to the page itself:

$('<input type="file" multiple>').on('change', function () {
  console.log(this.files);
}).click();

this.files on the second line is an array that contains filename, timestamps, size, and type.

Brad
  • 146,404
  • 44
  • 300
  • 476
9

Here's is a way of doing it without any Javascript and it's also compatible with any browser.


EDIT: In Safari, the input gets disabled when hidden with display: none. A better approach would be to use position: fixed; top: -100em.


<label>
  Open file dialog
  <input type="file" style="position: fixed; top: -100em">
</label>

Also, if you prefer you can go the "correct way" by using for in the label pointing to the id of the input like this:

<label for="inputId">file dialog</label>
<input id="inputId" type="file" style="position: fixed; top: -100em">
JP de la Torre
  • 1,311
  • 13
  • 16
  • @Stuffix I read it is because Safari will prevent hidden inputs from working. The workaround would be to hide it moving it out of sight using `position: fixed; top: -100em;` or `margin-top: -2em` and having `overflow: hidden` in the label. – JP de la Torre Sep 26 '15 at 01:14
2

you can't use input.click() directly, but you can call this in other element click event.

html

<input type="file">
<button>Select file</button>

js

var botton = document.querySelector('button');
var input = document.querySelector('input');
botton.addEventListener('click', function (e) {
    input.click();
});

this tell you Using hidden file input elements using the click() method

xavierskip
  • 356
  • 3
  • 9
0

I worked it around through this "hiding" div ...

<div STYLE="position:absolute;display:none;"><INPUT type='file' id='file1' name='files[]'></div>
Sandro Rosa
  • 441
  • 4
  • 10
0

How about make clicking the a tag, to click on the file button?

There is more browser support for this, but I use ES6, so if you really want to make it work in older and any browser, try to transpile it using babel, or just simply use ES5:

const aTag = document.getElementById("open-file-uploader");
const fileInput = document.getElementById("input-button");
aTag.addEventListener("click", () => fileInput.click());
#input-button {
  position: abosulte;
  width: 1px;
  height: 1px;
  clip: rect(1px 1px 1px 1px);
  clip: rect(1px, 1px, 1px, 1px);
}
<a href="#" id="open-file-uploader">Open file uploader</a>
<input type="file" id="input-button" />
Alireza
  • 83,698
  • 19
  • 241
  • 152
-1

I know this is an old post, but another simple option is using the INPUT TYPE="FILE" tag according to compatibility most major browser support this feature.

JJ.
  • 39
  • 1