181

Am trying to trigger an upload box (browse button) using jQuery.
The method I have tried now is:

$('#fileinput').trigger('click');   

But it doesn't seem to work. Please help. Thank you.

Shiladitya
  • 12,003
  • 15
  • 25
  • 38
Alec Smart
  • 94,115
  • 39
  • 120
  • 184
  • 2
    Depressing indeed, and it's triggered by 'click', seriously? I much prefer Flash/AS3, with its tight API and strong security model that only allows FileReference.browse to be called from a user-initiated input event handler. Furthermore, HTML file input is ugly and not stylable (it's just an input tag, so much for separation of content and style), so you have to make a new 'browse' button, which is also activated by a click event... which you have to forward to the file input as a click... which can lead to infinite recursion depending on element placement and event delegation specificity. – Triynko Nov 18 '15 at 18:04
  • 1
    Unfortunately, using Flash is becoming less and less viable, given its constant security issues, and the rise of content blockers. – Tim Nov 23 '15 at 17:43

21 Answers21

203

This is due to a security restriction.

I found out that the security restriction is only when the <input type="file"/> is set to display:none; or is visbilty:hidden.

So i tried positioning it outside the viewport by setting position:absolute and top:-100px; and voilà it works.

see http://jsfiddle.net/DSARd/1/

call it a hack.

Hope that works for you.

adardesign
  • 33,973
  • 15
  • 62
  • 84
125

this worked for me:

JS:

$('#fileinput').trigger('click'); 

HTML:

<div class="hiddenfile">
  <input name="upload" type="file" id="fileinput"/>
</div>

CSS:

.hiddenfile {
 width: 0px;
 height: 0px;
 overflow: hidden;
}

>>>Another one that works Cross-Browser:<<<

The Idea is that you overlay an invisible huge "Browse" button over your custom button. So when the user clicks your custom button, he's actually clicking on the "Browse" button of the native input field.

JS Fiddle: http://jsfiddle.net/5Rh7b/

HTML:

<div id="mybutton">
  <input type="file" id="myfile" name="upload"/>
  Click Me!
</div>

CSS:

div#mybutton {

  /* IMPORTANT STUFF */
  overflow: hidden;
  position: relative;   

  /* SOME STYLING */
  width:  50px;
  height: 28px;
  border: 1px solid green;
  font-weight: bold
  background: red;
}

div#mybutton:hover {
  background: green;
}

input#myfile {
  height: 30px;
  cursor: pointer;
  position: absolute;
  top: 0px;
  right: 0px;
  font-size: 100px;
  z-index: 2;

  opacity: 0.0; /* Standard: FF gt 1.5, Opera, Safari */
  filter: alpha(opacity=0); /* IE lt 8 */
  -ms-filter: "alpha(opacity=0)"; /* IE 8 */
  -khtml-opacity: 0.0; /* Safari 1.x */
  -moz-opacity: 0.0; /* FF lt 1.5, Netscape */
}

JavaScript:

$(document).ready(function() {
    $('#myfile').change(function(evt) {
        alert($(this).val());
    });
});
sled
  • 14,525
  • 3
  • 42
  • 70
  • There is one flaw, if you make the button wider, then in IE9/10 the invisible upload button is made of the right button and a left text-field. On this you have to double click. In this case try to set the font-size even bigger than 100px; – yunzen Jul 03 '14 at 14:06
  • This works even in Chrome 53. However, the `height` is suggested to change to `height: 100%` – Raptor Oct 25 '16 at 09:57
  • The second one even works in Safari on iOS. Very nice! – Jannis Aug 14 '19 at 14:50
89

You can use LABEL element ex.

<div>
    <label for="browse">Click Me</label>
    <input type="file" id="browse" name="browse" style="display: none">//
</div>

This will trigger the input file

C.Champagne
  • 5,381
  • 2
  • 23
  • 35
ATG
  • 1,090
  • 10
  • 12
  • I put in an edit just now, not noticing I wasn't' logged in and now I can;t edit it. In short, for accessibility reasons the label tag should include a tabindex="1" (whatever tab order index it should be) and role="button" attribute) – Peter Hanley Dec 01 '17 at 16:37
  • For the input I used: `opacity: 0; height: 0; width: 0; margin: 0; display: inline;` – Savage May 14 '19 at 17:33
  • Unfortunately this doesn't work in Safari on iOS :( – Jannis Aug 14 '19 at 14:47
18

I have it working (=tested) in IE8+, recent FF and chrome:

$('#uploadInput').focus().trigger('click');

The key is focusing before firing the click (otherwise chrome ignores it).

Note: you do NEED to have your input displayed and visible (as in, not display:none and not visibility:hidden). I suggest (as many other have before) to absolutely position the input and throw it off screen.

#uploadInput {
    position: absolute;
    left: -9999px;
}
The Mighty Rubber Duck
  • 4,388
  • 5
  • 28
  • 27
  • 1
    +1 for that. I also noticed that you can hide the surrounding element but not the file input button, then show the surrounding element, focus the button, activate it, then hide the button. – Stevo Jun 30 '12 at 07:29
12

Check out my fiddle.

http://jsfiddle.net/mohany2712/vaw8k/

.uploadFile {
  visibility: hidden;
}

#uploadIcon {
  cursor: pointer;
}
<body>
  <div class="uploadBox">
    <label for="uploadFile" id="uploadIcon">
      <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Icon_-_upload_photo_2.svg/512px-Icon_-_upload_photo_2.svg.png"  width="20px" height="20px"/>
    </label>
    <input type="file" value="upload" id="uploadFile" class="uploadFile" />
  </div>
</body>
Bhuwan
  • 16,525
  • 5
  • 34
  • 57
Mohan
  • 4,677
  • 7
  • 42
  • 65
11

Just for the sake of curiosity, you can do something like you want by dynamically creating an upload form and input file, without adding it to the DOM tree:

$('.your-button').on('click', function() {
    let uploadForm = document.createElement('form');
    let fileInput = uploadForm.appendChild(document.createElement('input'));
    
    fileInput.type = 'file';
    fileInput.name = 'images';
    fileInput.multiple = true;

    fileInput.click();
});
    

No need to add the uploadForm to the DOM.

jairhumberto
  • 535
  • 1
  • 11
  • 31
  • 1
    This is only half the story. To handle the result of the file selected before the `.click()` put ```$(fileInput).change(function() { alert(this.files[0].name); });```. Unless there's some magic submit going on here that I'm missing? – Jon Aug 25 '22 at 04:14
  • But this is another history, as the question was regard to a problem opening the "upload box", and this is just a tip. So yes, one would have to take care of handling the results. – jairhumberto Aug 25 '22 at 16:02
  • True true yes, I accept this answers the question 100% - but the caveat being as the element to send the data was created programmatically there's no existing JavaScript which could have been called - so the callback also needs to be created as well. Having said, great answer and this was the one I chose to use and upvoted your answer :) – Jon Aug 26 '22 at 14:35
  • Nice, your comment makes the answer complete! Thank you :) – jairhumberto Aug 27 '22 at 18:38
9

adardesign nailed it regarding the file input element being ignored when it is hidden. I also noticed many people shifting element size to 0, or pushing it out of bounds with positioning and overflow adjustments. These are all great ideas.
An alternative way that also seems to work perfectly well is to just set the opacity to 0. Then you can always just set the position to keep it from offsetting other elements as hide does. It just seems a little unnecessary to shift an element nearly 10K pixels in any direction.

Here's a little example for those who want one:

input[type='file']{
    position:absolute;
    opacity:0;
    /* For IE8 "Keep the IE opacity settings in this order for max compatibility" */
    -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
    /* For IE5 - 7 */
    filter: alpha(opacity=0);
}
saji89
  • 2,093
  • 4
  • 27
  • 49
eyegropram
  • 672
  • 4
  • 11
5

Actually, I found out a really easy method for this, which is:

$('#fileinput').show().trigger('click').hide();   

This way, your file input field can have the css property display on none and still win the trade :)

skywlkr
  • 1,185
  • 11
  • 22
5

Correct code:

<style>
    .upload input[type='file']{
        position: absolute;
        float: left;
        opacity: 0; /* For IE8 "Keep the IE opacity settings in this order for max compatibility" */
        -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* For IE5 - 7 */
        filter: alpha(opacity=0);
        width: 100px; height: 30px; z-index: 51
    }
    .upload input[type='button']{
        width: 100px;
        height: 30px;
        z-index: 50;
    }
    .upload input[type='submit']{
        display: none;
    }
    .upload{
        width: 100px; height: 30px
    }
</style>
<div class="upload">
    <input type='file' ID="flArquivo" onchange="upload();" />
    <input type="button" value="Selecionar" onchange="open();" />
    <input type='submit' ID="btnEnviarImagem"  />
</div>

<script type="text/javascript">
    function open() {
        $('#flArquivo').click();
    }
    function upload() {
        $('#btnEnviarImagem').click();
    }
</script>
Bruno Ribeiro
  • 1,280
  • 16
  • 21
E9 Sistemas
  • 51
  • 1
  • 1
4

It is too late to answer but I think this minimal setup work best. I am also looking for the same.

  <div class="btn-file">
     <input type="file" class="hidden-input">
     Select your new picture
  </div>

//css

.btn-file {
  display: inline-block;
  padding: 8px 12px;
  cursor: pointer;
  background: #89f;
  color: #345;
  position: relative;
  overflow: hidden;
}

.btn-file input[type=file] {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 100%;
  min-height: 100%;
  filter: alpha(opacity=0);
  opacity: 0;
  cursor: inherit;
  display: block;
}

jsbin

bootstrap file input buttons demo

Natwar Singh
  • 2,197
  • 4
  • 26
  • 42
4

This is a very old question, but unfortunately this issue is still relevant and requires a solution.

The (suprisingly simple) solution I've come up with is to "hide" the actual file input field and wrap it with a LABEL tag (can be based on Bootstrap and HTML5, for enhancement).

See here:Example code here

This way, the real file input field is invisible and all you see is the customized "button" which is actually a modified LABEL element. When you click on this LABEL element, the window for selecting a file comes up and the file you choose will go into the real file input field.

On top of that, you can manipulate the look and behaviour as you wish (for example: get the name of the selected file from the file input file, after selected, and show it somewhere. The LABEL element doesn't do that automatically, of course. I usually just put it inside the LABEL, as its text content).

Beware though! The manipulation of the look and behaviour of this is limited to whatever you can imagine and think of.    ;-)  ;-)

TheCuBeMan
  • 1,954
  • 4
  • 23
  • 35
4

I managed with a simple $(...).click(); with JQuery 1.6.1

Valentin Galea
  • 1,084
  • 8
  • 18
4

That's on purpose and by design. It's a security issue.

Chad Grant
  • 44,326
  • 9
  • 65
  • 80
3

or else simply

$(':input[type="file"]').show().click().hide();
Otvazhnii
  • 603
  • 5
  • 12
3

You can click the input file from your JQuery while keeping it hidden fully.

I am using this:

< input type="file" name="article_input_file" id="article_input_file" accept=".xlsx,.xls" style="display: none" >

$("#article_input_file").click();

this works from within any standard script tag in your HTML page.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
Dark Star
  • 43
  • 2
2

i had problems with custom client side validation for <input type="file"/> while using a fake button to trigger it and @Guillaume Bodi's solution worked for me (also with opacity: 0; on chrome)

$("#MyForm").on("click", "#fake-button", function () {
        $("#uploadInput").focus().trigger("click");
    });

and css style for upload input

#uploadInput {
opacity: 0.0; 
filter: alpha(opacity=0); /* IE lt 8 */
-ms-filter: "alpha(opacity=0)"; /* IE 8 */
-khtml-opacity: 0.0; /* Safari 1.x */
-moz-opacity: 0.0;
}
Amin K
  • 106
  • 1
  • 10
1

My problem was a little bit different on iOS 7. Turns out FastClick was causing problems. All I had to do was add class="needsclick" to my button.

Dex
  • 12,527
  • 15
  • 69
  • 90
1

Try this, it's a hack. the Position:absolute is for Chrome and trigger('change') is for IE.

var hiddenFile = $("<input type=\"file\" name=\"file\" id=\"file1\" style=\"position:absolute;left:-9999px\" />");
$('body').append(hiddenFile);

$('#aPhotoUpload').click(function () {
    hiddenFile.trigger('click');
    if ($.browser.msie)
        hiddenFile.trigger('change');
});

hiddenFile.change(function (e) {
    alert('TODO');
});
thinpiglin
  • 11
  • 1
0

This is probably the best answer, keeping in mind the cross browser issues.

CSS:

#file {
  opacity: 0;
  width: 1px;
  height: 1px;
}

JS:

$(".file-upload").on('click',function(){
   $("[name='file']").click();
});

HTML:

<a class="file-upload">Upload</a>
<input type="file" name="file">
Eddsters
  • 458
  • 1
  • 4
  • 16
0

I think i understand your problem, because i have a similar. So the tag <label> have the atribute for, you can use this atribute to link your input with type="file". But if you don't want to activate this using this label because some rule of your layout, you can do like this.

$(document).ready(function(){
  var reference = $(document).find("#main");
  reference.find(".js-btn-upload").attr({
     formenctype: 'multipart/form-data'
  });
  
  reference.find(".js-btn-upload").click(function(){
    reference.find("label").trigger("click");
  });
  
});
.hide{
  overflow: hidden;
  visibility: hidden;
  /*Style for hide the elements, don't put the element "out" of the screen*/
}

.btn{
  /*button style*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<div id="main">
<form enctype"multipart/formdata" id="form-id" class="hide" method="post" action="your-action">
  <label for="input-id" class="hide"></label>
  <input type="file" id="input-id" class="hide"/>
</form>

<button class="btn js-btn-upload">click me</button>
</div>

Of course you will adapt this for your own purpose and layout, but that's the more easily way i know to make it work!!

-1

Based on Guillaume Bodi's answer I did this:

$('.fileinputbar-button').on('click', function() {
    $('article.project_files > header, article.upload').show();
    $('article.project_files > header, article.upload header').addClass('active');
    $('.file_content, article.upload .content').show();
    $('.fileinput-button input').focus().click();
    $('.fileinput-button').hide();
});

which means it's hidden to start with and then displayed for the trigger, then hidden again immediately.

Stevo
  • 2,601
  • 3
  • 24
  • 32