23

I have simple piece of code to upload files:

$(document).ready(function () {
    $(".attachmentsUpload input.file").change(function () {
        $('form').submit();
    });
});

<form class="attachmentsUpload" action="/UploadHandler.ashx" method="post" enctype="multipart/form-data">
    <input type="file" class="file" name="file" />
</form>

While I click on input and then select a file in dialog box, I'm submitting this file using ajax. This is not important part here. Important part is, that while I select the same file second time in the dialog box, just after submitting the first file, the .change() event does not fire in IE and Chrome. But while I choose different file, the event fires and works properly. Under Firefox it is firing all the time.

How to workaround this, to work as expected (as in Firefox) ?

jwaliszko
  • 16,942
  • 22
  • 92
  • 158

2 Answers2

32

Description

This happens because the value of the input field (the selected filepath) does not change if you select the same file again.

You can set the value in the onChange() event to an empty string and submit your form only if the value is not empty. Have a look at my sample and this jsFiddle Demonstration.

Sample

$(".attachmentsUpload input.file").change(function () {
    if ($(".attachmentsUpload input.file").val() == "") {
        return;
    }
    // your ajax submit
    $(".attachmentsUpload input.file").val("");
});

Update

This, for any reason, does not work in IE9. You can replace the element to reset them. In this case you need jQuery live() to bind the event, because your input field will dynamically (re)created. This will work in all browsers.

I found this solution on the stackoverflow answer Clearing input type='file' using jQuery

$(".attachmentsUpload input.file").live("change", function () {
    if ($(".attachmentsUpload input.file").val() == "") {
        return;
    }
    // get the inputs value
    var fileInputContent = $(".attachmentsUpload input.file").val();
    // your ajax submit
    alert("submit value of the file input field=" + fileInputContent);
    // reset the field
    $(".attachmentsUpload input.file").replaceWith('<input type="file" class="file" name="file" />');
});​

More Information

Check out my updated jsFiddle

Note: live is now removed from later versions of jQuery. Please use on instead of live.

Community
  • 1
  • 1
dknaack
  • 60,192
  • 27
  • 155
  • 202
  • This helped for Chrome, but not for IE (IE9) – jwaliszko Apr 18 '12 at 17:57
  • @JarekWaliszko you are right. My answer is updated. – dknaack Apr 18 '12 at 18:02
  • @dknssck: Thanks for the effort, but for some reason this works in Chrome and Firefox, but doesn't submit a file to the server in IE (IE9, ContentLength equals to 0 at server side). – jwaliszko Apr 18 '12 at 18:14
  • @JarekWaliszko i think is happens because the ajax request is async. So you could try to save the value of the field in a variable before resetting it. Submit your variable then. my answer is updated – dknaack Apr 18 '12 at 18:19
  • Doing this check: `if ($(".attachmentsUpload input.file").val() == "") { return; }`wasn't actually needed, because it makes some trouble in IE. I've written an answer of what is working for me, based on your clues. – jwaliszko Sep 20 '12 at 14:02
  • for a general solution, see this post: http://stackoverflow.com/a/8863458/1188448. works in all browsers. – Sam Grondahl Feb 28 '13 at 15:43
  • 1
    Note that as of jQuery 1.7, the .live() method is deprecated, but .on() or .delegate() can be used instead. See the jQuery documentation at http://api.jquery.com/live/ for more information. – Ninjakannon Aug 12 '13 at 21:07
1

Based on dknaack answer, the clue is usage of jquery live to bind change event and resetting the input field after submit:

$(document).ready(function () {
    $(".attachmentsUpload input.file").change(function () {
        $('form').submit();  /* sync submit */
        $(".attachmentsUpload input.file").replaceWith('<input type="file" class="file" name="file" />');
    });
});

The resetting must be performed after submit event is done. When the submit is async, reset the field for example in ajax success event.

$(document).ready(function () {
    $(".attachmentsUpload input.file").change(function () {
        $('form').submit();  /* async submit */
    });
});

.ajaxForm({
    ...
    success: function (result) {
        // reset the field - needed for IE to upload the same file second time                    
        $this.find("input.file").replaceWith('<input type="file" class="file" name="file" />');
    }
});
jwaliszko
  • 16,942
  • 22
  • 92
  • 158