How can I detect when the user cancels a file input using an html file input?

onChange lets me detect when they choose a file, but I would also like to know when they cancel (close the file choose dialog without selecting anything).

28 Answers 28


While not a direct solution, and also bad in that it only (as far as I've tested) works with onfocus (requiring a pretty limiting event blocking) you can achieve it with the following:

document.body.onfocus = function(){ /*rock it*/ }

What's nice about this, is that you can attach/detach it in time with the file event, and it also seems to work fine with hidden inputs (a definite perk if you're using a visual workaround for the crappy default input type='file'). After that, you just need to figure out if the input value changed.

An example:

var godzilla = document.getElementById('godzilla')

godzilla.onclick = charge

function charge()
    document.body.onfocus = roar

function roar()
    if(godzilla.value.length) alert('ROAR! FILES!')
    else alert('*empty wheeze*')
    document.body.onfocus = null

See it in action: http://jsfiddle.net/Shiboe/yuK3r/6/

Sadly, it only seems to work on webkit browsers. Maybe someone else can figure out the firefox/IE solution

  • unfortunately this does not seem to work in mobile safari – gabriele.genta Feb 3 '14 at 15:57
  • I didn't want the focus event to fire every time, so I wanted to use addEventListener("focus",fn,{once: true}). However I couldn't get it to fire at all using document.body.addEventListener.. I don't know why. Instead I got the same result with window.addEventListener. – WoodenKitty Aug 13 '16 at 2:21
  • It works in FF on Ubuntu, but not on Windows. Strange... – Piotr Kowalski Oct 14 '16 at 22:30
  • Does not work every time. Tried on Chrome/Windows. – aagjalpankaj Apr 19 '17 at 5:24
  • 2
    This doesn't work in Firefox and Edge for me. However, listening for the mousemove event on window.document in addition to listening to focus on window seems to work everywhere (at least in modern browsers, I don't care about past-decade wrecks). Basically, any interaction event can be used for this task that is blocked by an opened file open dialog. – John Weisz Sep 3 '17 at 10:48

You can't.

The result of the file dialog is not exposed to the browser.

  • Is it possible to check whether or not the file chooser is open? – Ppp Jan 13 '11 at 14:34
  • 1
    @Ppp - No. The browser doesn't tell you that. – Oded Jan 13 '11 at 14:35
  • 5
    "The result of the file dialog is not exposed to the browser." This is not true if the dialog is closed by selecting a file. – Trevor Dec 1 '16 at 22:24
  • 1
    The change triggered by using the file dialog is exposed to the browser. See, if there is no file selected, and no file is selected afterwards, then nothing has changed, thus no change event is dispatched. – John Weisz Aug 18 '17 at 10:52
  • In addition, if a file is already selected, and you select the same file again, no change event is dispatched for that either. – Patrick Roberts Jul 13 '18 at 18:41
/* Tested on Google Chrome */
$("input[type=file]").bind("change", function() {
    var selected_file_name = $(this).val();
    if ( selected_file_name.length > 0 ) {
        /* Some file selected */
    else {
        /* No file selected or cancel/close
           dialog button clicked */
        /* If user has select a file before,
           when they submit, it will treated as
           no file selected */
  • 4
    Have you checked if your else statement ever gets evaluated? – jayarjo Dec 11 '16 at 9:43
  • as far as i remember when i wrote this answer, if user select a file and then re-select the file (but then cancelling), it will be treated as no file selected, i only use alert at the selected_file_name variable to test it. anyway, haven't tested it anymore since then. – Rizky K. Jan 24 '17 at 12:23
  • 2
    I can say, after some cross browser testing, that Firefox does not fire a change event on cancel, nor does it clear the existing files selected if re-opened and cancel clicked the second time. Strange, eh? – mix3d Jun 19 '17 at 19:16

When you select a file and click open/cancel, the input element should lose focus aka blur. Assuming the initial value of the input is empty, any non empty value in your blur handler would indicate an OK, and an empty value would mean a Cancel.

UPDATE: The blur is not triggered when the input is hidden. So can't use this trick with IFRAME-based uploads, unless you want to temporarily display the input.

  • 2
    In Firefox 10 beta and Chrome 16, blur is not triggered when you select a file. Haven't tried in other browsers. – Blaise Jan 3 '12 at 12:21
  • 1
    That doesn't work - blur on input is triggered immediately after click. Chrome 63.0.3239.84 x64 on Win7. – Qwertiy Dec 27 '17 at 17:55

You can catch the cancel if you choose the same file as previously and you click cancel: in this case.

You can do it like this:

<input type="file" id="myinputfile"/>
document.getElementById('myinputfile').addEventListener('change', myMethod, false);
function myMethod(evt) {
  var files = evt.target.files; 
  f= files[0];
  if (f==undefined) {
     // the user has clicked on cancel
  else if (f.name.match(".*\.jpg")|| f.name.match(".*\.png")) {
     //.... the user has choosen an image file
     var reader = new FileReader();
     reader.onload = function(evt) { 
        try {
         } catch (err) {
  • 1
    Thnkx @loveJs this post really helped me. – VPK Mar 20 '13 at 11:03
  • 4
    Not exactly, if the user selects the same file it's not a cancel =( – Tiago Peres França Nov 8 '13 at 13:27
  • 12
    onchange only fires if there was a change. So if the file is the same file as previous the onchange listener will not fire. – Shane Feb 13 '14 at 0:04
  • 1
    You can clear the input selection (input.value = '') after you detect the first change, so that the second time onchange will fire even if user selects the same file again. – Chris Dec 6 '17 at 1:53
  • 1
    @CodeGems it is allowed to programmatically set the input.value to an empty string. But you are right that setting it to any other value is not allowed. – Chris Dec 6 '17 at 14:07

Just listen to the click event as well.

Following from Shiboe's example, here's a jQuery example:

var godzilla = $('#godzilla');
var godzillaBtn = $('#godzilla-btn');

godzillaBtn.on('click', function(){

godzilla.on('change click', function(){

    if (godzilla.val() != '') {
        $('#state').html('You have chosen a Mech!');    
    } else {
        $('#state').html('Choose your Mech!');


You can see it in action here: http://jsfiddle.net/T3Vwz

  • 1
    I tested on Chrome 51, it doesn't work the first time you select files. The solution is to add a delay: jsfiddle.net/7jfbmunh – Benoit Blanchon Jun 21 '16 at 14:33
  • Your fiddle did not work for me - using Firefox 58.0.2 – barrypicker Mar 15 '18 at 2:38

So I'll throw my hat into this question since I came up with a novel solution. I have a Progressive Web App which allows users to capture photos and videos and upload them. We use WebRTC when possible, but fall back to HTML5 file pickers for devices with less support *cough Safari cough*. If you're working specifically on an Android/iOS mobile web application which uses the native camera to capture photos/videos directly, then this is the best solution I have come across.

The crux of this problem is that when the page loads, the file is null, but then when the user opens the dialog and presses "Cancel", the file is still null, hence it did not "change", so no "change" event is triggered. For desktops, this isn't too bad because most desktop UI's aren't dependent on knowing when a cancel is invoked, but mobile UI's which bring up the camera to capture a photo/video are very dependent on knowing when a cancel is pressed.

I originally used the document.body.onfocus event to detect when the user returned from the file picker, and this worked for most devices, but iOS 11.3 broke it as that event is not triggered.


My solution to this is *shudder* to measure CPU timing to determine if the page is currently in the foreground or the background. On mobile devices, processing time is given to the app currently in the foreground. When a camera is visible it will steal CPU time and deprioritize the browser. All we need to do is measure how much processing time our page is given, when camera launches our available time will drop drastically. When the camera is dismissed (either cancelled or otherwise), our available time spike back up.


We can measure CPU timing by using setTimeout() to invoke a callback in X milliseconds, and then measure how long it took to actually invoke it. The browser will never invoke it exactly after X milliseconds, but if it is reasonable close then we must be in the foreground. If the browser is very far away (over 10x slower than requested) then we must be in the background. A basic implementation of this is like so:

function waitForCameraDismiss() {
  const REQUESTED_DELAY_MS = 25;
  const MAX_TRIALS_TO_RECORD = 10;

  const triggerDelays = [];
  let lastTriggerTime = Date.now();

  return new Promise((resolve) => {
    const evtTimer = () => {
      // Add the time since the last run
      const now = Date.now();
      triggerDelays.push(now - lastTriggerTime);
      lastTriggerTime = now;

      // Wait until we have enough trials before interpreting them.
      if (triggerDelays.length < MAX_TRIALS_TO_RECORD) {
        window.setTimeout(evtTimer, REQUESTED_DELAY_MS);

      // Only maintain the last few event delays as trials so as not
      // to penalize a long time in the camera and to avoid exploding
      // memory.
      if (triggerDelays.length > MAX_TRIALS_TO_RECORD) {

      // Compute the average of all trials. If it is outside the
      // acceptable margin of error, then the user must have the
      // camera open. If it is within the margin of error, then the
      // user must have dismissed the camera and returned to the page.
      const averageDelay =
          triggerDelays.reduce((l, r) => l + r) / triggerDelays.length
      if (averageDelay < MAX_REASONABLE_DELAY_MS) {
        // Beyond any reasonable doubt, the user has returned from the
        // camera
      } else {
        // Probably not returned from camera, run another trial.
        window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
    window.setTimeout(evtTimer, REQUESTED_DELAY_MS);

I tested this on recent version of iOS and Android, bringing up the native camera by setting the attributes on the <input /> element.

<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />

This works out actually a lot better than I expected. It runs 10 trials by requesting a timer to be invoked in 25 milliseconds. It then measures how long it actually took to invoke, and if the average of 10 trials is less than 50 milliseconds, we assume that we must be in the foreground and the camera is gone. If it is greater than 50 milliseconds, then we must still be in the background and should continue to wait.

Some additional details

I used setTimeout() rather than setInterval() because the latter can queue multiple invocations which execute immediately after each other. This could drastically increase the noise in our data, so I stuck with setTimeout() even though it is a little more complicated to do so.

These particular numbers worked well for me, though I have see at least once instance where the camera dismiss was detected prematurely. I believe this is because the camera may be slow to open, and the device may run 10 trials before it actually becomes backgrounded. Adding more trials or waiting some 25-50 milliseconds before starting this function may be a workaround for that.


Unfortuantely, this doesn't really work for desktop browsers. In theory the same trick is possible as they do prioritize the current page over backgrounded pages. However many desktops have enough resources to keep the page running at full speed even when backgrounded, so this strategy doesn't really work in practice.

Alternative solutions

One alternative solution not many people mention that I did explore was mocking a FileList. We start with null in the <input /> and then if the user opens the camera and cancels they come back to null, which is not a change and no event will trigger. One solution would be to assign a dummy file to the <input /> at page start, therefore setting to null would be a change which would trigger the appropriate event.

Unfortunately, there's no way official way to create a FileList, and the <input /> element requires a FileList in particular and will not accept any other value besides null. Naturally, FileList objects cannot be directly constructed, do to some old security issue which isn't even relevant anymore apparently. The only way to get ahold of one outside of an <input /> element is to utilize a hack which copy-pastes data to fake a clipboard event which can contain a FileList object (you're basically faking a drag-and-drop-a-file-on-your-website event). This is possible in Firefox, but not for iOS Safari, so it was not viable for my particular use case.

Browsers, please...

Needless to say this is patently ridiculous. The fact that web pages are given zero notification that a critical UI element has changed is simply laughable. This is really a bug in the spec, as it was never intended for a full-screen media capture UI, and not triggering the "change" event is technically to spec.

However, can browser vendors please recognize the reality of this? This could be solved with either a new "done" event which is triggered even when no change occurs, or you could just trigger "change" anyways. Yeah, that would be against spec, but it is trivial for me to dedup a change event on the JavaScript side, yet fundamentally impossible to invent my own "done" event. Even my solution is really just heuristics, if offer no guarantees on the state of the browser.

As it stands, this API is fundamentally unusable for mobile devices, and I think a relatively simple browser change could make this infinitely easier for web developers *steps off soap box*.


The easiest way is to check if there are any files in temporary memory. If you want to get the change event every time user clicks the file input you can trigger it.

var yourFileInput = $("#yourFileInput");

yourFileInput.on('mouseup', function() {
}).on('change', function() {
    if (this.files.length) {
        //User chose a picture
    } else {
        //User clicked cancel

Most of these solutions don't work for me.

The problem is that you never know which event will be triggered fist, is it click or is it change? You can't assume any order, because it probably depends on the browser's implementation.

At least in Opera and Chrome (late 2015) click is triggered just before 'filling' input with files, so you will never know the length of files.length != 0 until you delay click to be triggered after change.

Here is code:

var inputfile = $("#yourid");

inputfile.on("change click", function(ev){
    if (ev.originalEvent != null){
        console.log("OK clicked");
    document.body.onfocus = function(){
        document.body.onfocus = null;
            if (inputfile.val().length === 0) console.log("Cancel clicked");
        }, 1000);

Shiboe's solution would be a good one if it worked on mobile webkit, but it doesn't. What I can come up with is to add a mousemove event listener to some dom object at the time that the file input window is opened, like so:

 $('.upload-progress').mousemove(function() {
      checkForFiles = function(me) {
        var filefield = $('#myfileinput');
        var files = filefield.get(0).files;
        if (files == undefined || files[0] == undefined) $(me).remove(); // user cancelled the upload

The mousemove event is blocked from the page while the file dialog is open, and when its closed one checks to see if there are any files in the file input. In my case I want an activity indicator blocking things till the file is uploaded, so I only want to remove my indicator on cancel.

However this doesn't solve for mobile, since there is no mouse to move. My solution there is less than perfect, but I think its good enough.

       $('.upload-progress').bind('touchstart', function() {

Now we're listening for a touch on the screen to do the same files check. I'm pretty confident that the user's finger will be put on the screen pretty quickly after cancel and dismiss this activity indicator.

One could also just add the activity indicator on the file input change event, but on mobile there is often a few seconds lag between selecting the image and the change event firing, so its just much better UX for the activity indicator to be displayed at the start of the process.


I know this is a very old question but just in case it helps someone, I found when using the onmousemove event to detect the cancel, that it was necessary to test for two or more such events in a short space of time. This was because single onmousemove events are generated by the browser (Chrome 65) each time the cursor is moved out of the select file dialog window and each time it is moved out of the main window and back in. A simple counter of mouse movement events coupled with a short duration timeout to reset the counter back to zero worked a treat.

  • 1
    The first paragraph is a good answer, even though it could be splitted to multiple one for better readability. But those two "SOAPBOX" lines make it borderline to a Non-Answer as questions don't belong in answers. Can you reword/rephrase your answer a bit? Thank you. – Filnor Apr 18 '18 at 12:14

In my case i had to hide submit button while users were selecting images.

This is what i come up:

$(document).on('click', '#image-field', function(e) {
  $('.submit-button').prop('disabled', true)
$(document).on('focus', '#image-field'), function(e) {
  $('.submit-button').prop('disabled', false)

#image-field is my file selector. When somenone clicks on it, i disable the form submit button. The point is, when the file dialog closed - doesn't matter they select a file or cancel - #image-field got the focus back, so i listen on that event.


I found that, this does not work in safari and poltergeist/phantomjs. Take this info into account if you would like to implement it.


Combining Shiboe's and alx's solutions, i've got the most reliable code:

var selector = $('<input/>')
   .attr({ /* just for example, use your own attributes */
      "id": "FilesSelector",
      "name": "File",
      "type": "file",
      "contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/
   .on("click.filesSelector", function () {
      /* do some magic here, e.g. invoke callback for selection begin */
      var cancelled = false; /* need this because .one calls handler once for each event type */
      setTimeout(function () {
         $(document).one("mousemove.filesSelector focusin.filesSelector", function () {
            /* namespace is optional */
            if (selector.val().length === 0 && !cancelled) {
               cancelled = true; /* prevent double cancel */
               /* that's the point of cancel,   */
      }, 1); /* 1 is enough as we just need to delay until first available tick */
   .on("change.filesSelector", function () {
      /* do some magic here, e.g. invoke callback for successful selection */
   .appendTo(yourHolder).end(); /* just for example */

Generally, mousemove event does the trick, but in case user made a click and than:

  • cancelled file open dialog by escape key (without moving a mouse), made another accurate click to open file dialog again...
  • switched focus to any other application, than came back to browser's file open dialog and closed it, than opened again via enter or space key...

... we won't get mousemove event hence no cancel callback. Moreover, if user cancels second dialog and makes a mouse move, we'll get 2 cancel callbacks. Fortunately, special jQuery focusIn event bubbles up to the document in both cases, helping us to avoid such situations. The only limitation is if one blocks focusIn event either.

  • I caught the mousemove event on document during selecting files in the OS dialog in Chrome 56.0.2924.87 on Ubuntu 16.10. No problem, when not moving the mouse, or using just keyboard to select the file. I had to replace mousemove by keydown to detect the cancel as early as possible, but not "too early", when the dialog was still open. – Ferdinand Prantl Feb 17 '17 at 23:09

I see that my response would be quite outdated, but never the less. I faced with the same problem. So here's my solution. The most useful code snipped was KGA's one. But it isn't totally working and is a bit complicated. But I simplified it.

Also, the main trouble maker was that fact, that 'change' event doesn't come instantly after focus, so we have to wait for some time.

"#appendfile" - which user clicks on to append a new file. Hrefs get focus events.

$("#appendfile").one("focusin", function () {
    // no matter - user uploaded file or canceled,
    // appendfile gets focus
    // change doesn't come instantly after focus, so we have to wait for some time
    // wrapper represents an element where a new file input is placed into
        if (wrapper.find("input.fileinput").val() != "") {
            // user has uploaded some file
            // add your logic for new file here
        else {
            // user canceled file upload
            // you have to remove a fileinput element from DOM
    }, 900);

You can detect this only in limited circumstances. Specifically, in chrome if a file was selected earlier and then the file dialog is clicked and cancel clicked, Chrome clears the file and fires the onChange event.


In this scenario, you can detect this by handling the onChange event and checking the files property.


The following seems to work for me (on desktop, windows):

var openFile = function (mimeType, fileExtension) {
    var defer = $q.defer();
    var uploadInput = document.createElement("input");
    uploadInput.type = 'file';
    uploadInput.accept = '.' + fileExtension + ',' + mimeType;

    var hasActivated = false;

    var hasChangedBeenCalled = false;
    var hasFocusBeenCalled = false;
    var focusCallback = function () {
        if (hasActivated) {
            hasFocusBeenCalled = true;
            document.removeEventListener('focus', focusCallback, true);
            setTimeout(function () {
                if (!hasChangedBeenCalled) {
                    uploadInput.removeEventListener('change', changedCallback, true);
            }, 300);

    var changedCallback = function () {
        uploadInput.removeEventListener('change', changedCallback, true);
        if (!hasFocusBeenCalled) {
            document.removeEventListener('focus', focusCallback, true);
        hasChangedBeenCalled = true;
        if (uploadInput.files.length === 1) {
            //File picked
            var reader = new FileReader();
            reader.onload = function (e) {
        else {
    document.addEventListener('focus', focusCallback, true); //Detect cancel
    uploadInput.addEventListener('change', changedCallback, true); //Detect when a file is picked
    hasActivated = true;
    return defer.promise;

This does use angularjs $q but you should be able to replace it with any other promise framework if needed.

Tested on IE11, Edge, Chrome, Firefox, but it does not seem to work on Chrome on a Android Tablet as it does not fire the Focus event.


The file-type field, frustratingly, doesn't respond to a lot of events (blur would be lovely). I see a lot of people suggesting change-oriented solutions and them getting downvoted.

change does work, but it has a major flaw (vs what we want to happen).

When you freshly load a page containing a file field, open the box and press cancel. Nothing, frustratingly, changes.

What I chose to do is load in a gated-state.

  • The next part of the form a section#after-image in my case is hidden from view. When my file field changes, an upload button is shown. Upon successful upload, section#after-image is shown.
  • If the user loads, opens the file-dialog, then cancels out, they never see the upload button.
  • If the user chooses a file, the upload button is shown. If they then open the dialog and cancel, the change event is triggered by this cancel, and there I can (and do) re-hide my upload button until a proper file is selected.

I was fortunate that this gated-state was already the design of my form. You do not need to use the same style, merely having the upload button initially hidden and upon change, setting a hidden field or javascript variable to something you can monitor on submit.

I tried changing the value of files[0] before the field was interacted with. This didn't do anything regarding onchange.

So yes, change works, at least as good as we're going to get. The filefield is secured, for obvious reasons, but to the frustration of well-intentioned developers.

It's not fitting to my purpose, but you might be able to, onclick, load a warning prompt (not an alert(), because that stalls page-processing), and hide it if change is triggered and files[0] is null. If change is not triggered, the div remains in its state.


There is a hackish way to do this (add callbacks or resolve some deferred/promise implementation instead of alert() calls):

var result = null;

$('<input type="file" />')
    .on('change', function () {
        result = this.files[0];

setTimeout(function () {
    $(document).one('mousemove', function () {
        if (!result) {
}, 1000);

How it works: while file selection dialog is open, document does not receive mouse pointer events. There is 1000ms delay to allow the dialog to actually appear and block browser window. Checked in Chrome and Firefox (Windows only).

But this is not a reliable way to detect cancelled dialog, of course. Though, might improve some UI behavior for you.

  • One major drawback is on phones and tablets, they don't use mice normally! – Peter Sep 14 '17 at 8:15

Here is my solution, using the file input focus (not using any timers)

var fileInputSelectionInitiated = false;

function fileInputAnimationStart() {
    fileInputSelectionInitiated = true;
    if (!$("#image-selector-area-icon").hasClass("fa-spin"))
    if (!$("#image-selector-button-icon").hasClass("fa-spin"))

function fileInputAnimationStop() {
    fileInputSelectionInitiated = false;

$("#image-selector-area-wrapper").click(function (e) {

$("#preview-image-wrapper").click(function (e) {

$("#fileinput").click(function (e) {

$("#fileinput").focus(function (e) {

$("#fileinput").change(function(e) {
    // ...

  • Running your snippet gives me Error: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 } – connexo Jun 6 '18 at 13:24

This is hacky at best, but here is a working example of my solution to detect whether or not a user has uploaded a file, and only allowing them to proceed if they have uploaded a file.

Basically hide the Continue, Save, Proceed or whatever your button is. Then in the JavaScript you grab the file name. If the file name does not have a value, then do not show the Continue button. If it does have a value, then show the button. This also works if they at first upload a file and then they try to upload a different file and click cancel.

Here is the code.


<div class="container">
<div class="row">
    <input class="file-input" type="file" accept="image/*" name="fileUpload" id="fileUpload" capture="camera">
    <label for="fileUpload" id="file-upload-btn">Capture or Upload Photo</label>
<div class="row padding-top-two-em">
    <input class="btn btn-success hidden" id="accept-btn" type="submit" value="Accept & Continue"/>
    <button class="btn btn-danger">Back</button>


$('#fileUpload').change(function () {
    var fileName = $('#fileUpload').val();
    if (fileName != "") {
    } else {
        $('#file-upload-btn').html("Upload File");


.file-input {
    width: 0.1px;
    height: 0.1px;
    opacity: 0;
    overflow: hidden;
    position: absolute;
    z-index: -1; 

.file-input + label {
    font-size: 1.25em;
    font-weight: normal;
    color: white;
    background-color: blue;
    display: inline-block;
    padding: 5px;

.file-input:focus + label,
.file-input + label:hover {
    background-color: red;

.file-input + label {
    cursor: pointer;

.file-input + label * {
    pointer-events: none;

For the CSS a lot of this is to make the website and button accessible for everyone. Style your button to whatever you like.


Well, this doesn't exactly answers your question. My assumption is that, you have a scenario, when you add a file input, and invoke file selection, and if user hits cancel, you just remove the input.

If this is the case, then: Why adding empty file input?

Create the one on the fly, but add it to DOM only when it is filled in. Like so:

    var fileInput = $("<input type='file' name='files' style='display: none' />");
    fileInput.bind("change", function() {
        if (fileInput.val() !== null) {
            // if has value add it to DOM

So here I create <input type="file" /> on the fly, bind to it's change event and then immediately invoke click. On change will fire only when user selects a file and hits Ok, otherwise input will not be added to DOM, therefore will not be submitted.

Working example here: https://jsfiddle.net/69g0Lxno/3/


//Use hover instead of blur

var fileInput = $("#fileInput");

if (fileInput.is(":hover") { 

} else {


If you already require JQuery, this solution might do the work (this is the exact same code I actually needed in my case, although using a Promise is just to force the code to wait until file selection has been resolved):

await new Promise(resolve => {
    const input = $("<input type='file'/>");
    input.on('change', function() {
    $('body').one('focus', '*', e => {



I found this atribute, its most simple yet.

if ($('#selectedFile')[0].files.length > 1)
   // Clicked on 'open' with file
} else {
   // Clicked on 'cancel'

Here, selectedFile is an input type=file.

  • This is a good solution for me, except that it should be >= 1 – Bron Thulke Nov 3 '17 at 1:06
function file_click() {
    document.body.onfocus = () => {
            let file_input = document.getElementById('file_input');
            if (!file_input.value) alert('please choose file ')
            else alert(file_input.value)
            document.body.onfocus = null

Using setTimeout to get the certain value of the input.


You can make a jquery change listener on the input field and detect that user cancel or closed upload window by the value of the field.

here is an example:

//when upload button change
    //get uploaded file
    var file = this.files[0];

    //if user choosed a file
        //upload file or perform your desired functiuonality
        //user click cancel or close the upload window

I needed to do it and I ended up creating a very simple solution. Can be seen here: http://jsfiddle.net/elizeubh2006/1w711q0y/5/

(But will only work after a first file selection has occurred. For me it was useful because the onchange event was being called even when the user clicked cancel. The user chose a file, then clicked to select another file, but canceled and the onchange was called.)

   $("#inputFileId").on("change", function() {
 var x = document.getElementById('inputFileId');
    if(x.files.length == 0)
    alert('cancel was pressed');

  • Unfortunately this doesn't work on iOS mobile Safari. – Patrick Rudolph Apr 7 '15 at 13:32
  • It will not work because the change only is fired only when a file is selected, also the selected file should be different from a previously selected file. – Oussama Elgoumri Jul 29 '15 at 23:01
  • "will only work after a first file selection has occurred" -> jsfiddle.net/elizeubh2006/1w711q0y/5 – user3812703 Aug 3 '15 at 12:35
  • "will only work after a first selection" << This is not quite accurate. It doesn't work, for example, if you 1) Select, 2) Cancel, 3) Cancel. It will "detect" the first cancel, but not the second. – Trevor Dec 2 '16 at 23:03

input type=file code:

onchange="if(this.files[0]!=undefined){ UploadImg(); }else{ alert('cancel'); }"

Your Answer

