jQuery File Download v1.4.0 released with promise support

I’ve been neglecting jquery.fileDownload.js a little bit while working on my Durandal.js and FluentKnockoutHelpers demo but since that’s mostly wrapped up I have merged some pulls and added promise support to jQuery File Download. Promises make using the plugin a whole lot cleaner. If you haven’t used them yet start to they are awesome! Enjoy!

As usual the source can be obtained here:

https://github.com/johnculviner/jquery.fileDownload

A short example of what you can now do:

$.fileDownload('some/file/url')
    .done(function () { alert('File download a success!'); })
    .fail(function () { alert('File download failed!'); });

 

63 thoughts on “jQuery File Download v1.4.0 released with promise support

  1. Hi John!
    I’m trying to use your plugin for download dynamically generated pdf from server, but I’m getting error: “Uncaught TypeError: Cannot read property ‘undefined’ of undefined”. Code snippet: $.fileDownload('Trips/AsyncPrint', {
    successCallback: function (url) {
    alert('done!');
    },
    failCallback: function (responseHtml, url) {
    alert('fail.');
    },
    httpMethod: "POST",
    data: JSON.stringify(d)
    });

    What’s wrong? Thanks for reply and have a nice day… 🙂

  2. Hi John,

    This plugin has been very useful for me, I just had an issue trying to send a parameter when the symbol “=” is present in some field value as the value is not been send complete in the request, to solve this, I just replaced the logic to parse the URL attributes to send those as hidden elements in the form for a POST method. This was my change:

    var search = /([^&=]+)=?([^&]*)/g;
    var match = null,
    key = null,
    value = null;

    while (match = search.exec(settings.data)) {
    key = match[1]
    if (key) {
    value = settings.encodeHTMLEntities ? htmlSpecialCharsEntityEncode(decodeURIComponent(match[2])) : decodeURIComponent(match[2]);
    formInnerHtml += "";
    }
    }

    Please, let me know what do you think about it?

    Gabo

  3. How can I use this on my asp.net webforms project? Can you please post some codes on how to use this in webforms. thanks

  4. I have problem.

    I have such code
    $(function()
    {
    $(document).on(“click”, “a.download”, function()
    {
    $.fileDownload($(this).prop(‘href’))
    .done(function() { alert(‘File download a success!’); })
    .fail(function() { alert(‘File download failed!’); });
    return false;
    });

    });

    but File download a success! has neved appeared. File is downloaded but successCallback (.done) does no trigger. any ideas?

    1. You may need to try and add $.proxy from Jquery. I had to use it recently for a project. It stems from how Javascript handles scopes.

      .done $.proxy(function(args) {
      doStuff();
      }, this)}

      Something like that may work, I have not tested it.

  5. I would like to suggest that when you hide the iframe in your plugin, instead of doing .hide() or display:none, you should do position:absolute;top:-10000px; or the like. This is because if the iframe has js code that runs when the page loads that tries to manipulate the DOM it will fail if the frame is hidden. BTW, this is the case especially in IE.

  6. I am attempting to use your plugin to allow users to download jpeg files. The code works without generating an error, however, it also does NOT initiate the download process. Because the content can be rendered by the browser, it simply is rendered (yet kept invisible) in the iframe.

    I am at a loss with this situation. I’ve been working on this problem for some time. Your assistance is greatly appreciated.

    Thanks,

    – John.

    1. Are you setting Content-Disposition: attachment;filename=(file)?
      If so, have you tried also plugging in a bogus MIME type to prevent the browser from realizing it’s an image?

  7. Hello
    is there any crossdomain configuration to setup on the server where the files are hosted ? i’m trying your script and it’s working if i set 1 of your example files as target, but i get an “error occured” when trying with a pdf hosted on my server (yes, i double checked the file url to make sure it is the good one).
    any thoughts ?

    thank you for your help

      1. hey…john
        i am not able to implement this plugin in my mvc4 site. i want to show waiting dialog for my diff excel file’s download period.
        can you tell me exact steps for that??
        please?

  8. The plugin is great,

    One problem though, if the cookie was not set and you try to download the file, the function checkFileDownloadComplete() { … } will get into the infinite loop and failCallback doesn’t get called. You can replicate it by putting console.log(‘something’) at the beginning of the function. Tested on Chrome and FF.

      1. John,

        It works, actually. It works in my tests as well. If attachment is there the cookie gets set and download is initiated. If the attachment is not there, the cookie is not set and download is not initiated and I’m not redirected 🙂 but, checkFileDownloadComplete keeps spinning in setInterval.

        1. Wow, embarrassing 🙂 it was my mistake on the server. It was returning internal server error AND the attachment header messing up the browser. It works great.

          Thank you.

  9. Hello John,

    I’m getting the following error:

    Resource interpreted as Document but transferred with MIME type image/png

    Same error with all file types. I tried some code modifications on my site but nothing works.

    Can you help me please?

    Kind regards!

  10. Hi John,

    Excellent plugin, i’ve got the following code working to download files and it successfully displays error if file not found and displays the please wait while we prepare your file message. However, when the file download begins, the message should disappear like it does on your demo but its not disappearing in my code below. Any ideas what i’m doing wrong?


    $(document).on("click", "a.fileDownloadSimpleRichExperience", function () {
    $.fileDownload($(this).prop('href'), {
    preparingMessageHtml: "We are preparing your report, please wait...",
    failMessageHtml: "There was a problem generating your report, please try again."
    });
    return false; //this is critical to stop the click event which will trigger a normal file download!
    });

    download

      1. Thanks for your reply John, didnt see anything about adding a cookie. At what point do I add the cookie? and what cookie? you got any examples?

        1. I’ve put the line:

          document.cookie = settings.cookieName + “=true; path=” + settings.cookiePath;

          last in the onPrepare-function.

          By that I did not need to have it set by code.


          onPrepare: function (url) {

          //wire up a jquery dialog to display the preparing message if specified
          if (settings.preparingMessageHtml) {

          $preparingDialog = $("").html(settings.preparingMessageHtml).dialog(settings.dialogOptions);

          } else if (settings.prepareCallback) {

          settings.prepareCallback(url);

          }

          // Set the cookie each time the function is prepared // Klaus
          document.cookie = settings.cookieName + "=true; path=" + settings.cookiePath;
          }

  11. I think , the code should also check for the cookie in the document of iframe. When I wrote cookie, it wrote in the iframe.document instead of current document. I modified the code to do this:
    var cookieDoc = downloadWindow ? downloadWindow.document : getiframeDocument($iframe);
    if (cookieDoc.cookie.indexOf(settings.cookieName + “=” + settings.cookieValue) != -1) {

    //execute specified callback
    internalCallbacks.onSuccess(fileUrl);

    //remove the cookie and iframe
    cookieDoc.cookie = settings.cookieName + “=; expires=” + new Date(1000).toUTCString() + “; path=” + settings.cookiePath;

    cleanUp(false);

    return;
    }

  12. John,

    I am using your library to download some Excel reports, but am having some issues running a long-polling type of progress check. I set up an interval in the prepareCallback to check a progress URL on the server, but it only runs once and doesn’t return until after the download has completed.

    Any ideas as to why your iFrame form submission would cause other XMLHTTPRequest’s to block?

    Thanks for your help with this.

  13. Hi John,
    i am using the plugin and it is working fine for desktop browsers. but on Mobile browsers [Android and Ios] it is making two calls to server to get the response. both the calls are returning with a downloadable PDF document, but the token is getting expired.
    Please let me know if we can restrict it to make only one call from Android and Ios browsers ?

  14. So, I’m researching using your code to invoke a POST of a JSON body to my internal server to push a file to my end user. The problem is, like Sebastian, who I think is trying to do the same thing or similar, that your code doesn’t have the ability to push a JSON body to the server; and probably rightly so. Looking at your code, it seems that you’re “tricking” the client into creating and submitting either an iframe or a new document window to make the call to the server with the form entities within the respective container.

    I’m researching more to patch your 1.4.2 script to allow such an ability, if possible. I’m just reaching out to see if you could lend some pointers on whether it’s doable or not.

    Thanks!

  15. Hi, great plugin!

    Success is working fine, but my fail callback never gets called even though my server response looks the same as on the demo page for failures — except my Content-Type is “text/xml” instead of your “text/html”. Is that it?

    $.fileDownload(url, {httpMethod:’POST’, data: {“from”:”jquery.fileDownload”}})
    .done(function (url) { $.bootstrapGrowl($(event.target).text() + ” – download successful! “, {“ele”: event.target, “type”:”success”, “width”: “auto”}); })
    .fail(function (responseHtml, url) { $.bootstrapGrowl(responseHtml + $(event.target).text() + ” – download failed! “, {“type”:”error”, “width”: “auto”}); });

    Thanks!

    1. I changed the response to use Content-Type “xml/html” and the fail callback works. Should have tried that first (arg is “responseHtml” after all) 🙂

  16. i am not able to implement this plugin in my mvc4 website.
    i want to display waiting dialog box.
    can any one tell me exact steps for this process??
    please??

  17. Hi,

    I want to get the size of the file before the file gets downloaded. Is it possible?

    Thanks in Advance,
    Gupta.

  18. Hello, Nice feature!

    The callback functions (either using “.done()” or “successCallback” ) in my case never get executed.
    I just return a Content-type: application/vnd.ms-excel and Content-Disposition: attachment response and i have this js code:
    $.fileDownload(url)
    .done(function () { alert(‘success test’); })
    .fail(function () { alert(‘fail test’); });
    What am i missing?
    Thanks.

  19. Its a great plugin and I have easily implemented the success scenario.
    But am not able to handle the failure scenario.
    In the event of failure, I m setting the cookie as “fileDownload=true; expiry=” on the server, but failCallback is not being invoked.

    Is this enough or should I do something else? I m using java for server programming.

    Would be very glad on your response.

  20. For those want to use a “JSON” powered file downloader (for example to call a WebMethod on .NET) i’ve changed the file a little bit:

    http://www.papersoft.it/jquery-download-con-parametri-json/

    Direct JS link: http://www.papersoft.it/wp-content/misc/jQuery.fileDownload.js

    I’m sure my changes can be refactored.. but i have no time at moment..
    To use json parameters you can use a call like

    $.fileDownload("", {
    httpMethod: "POST",
    data: dataToSendExport,
    contentType: "application/json"
    })
    .fail(function () { alert("Error during export") });

    where dataToSendExport is an array of objects built like:


    dataToSendExport[0] = { "tableName": tableName };
    dataToSendExport[1] = { "columns": replaceAll("\'", "\\'", JSON.stringify(columns)) };

    Hope you find it useful

  21. Hello John,

    First I would like to thank you for the very nice job that you done.
    This plugin is the very best extension that I can found for make my application.

    I’ve just a problem with the “done” callback : it’s don’t work.
    The file is well downloaded but the callback is not taken into consideration.

    The “fail” callback is working good.

    That’s my code :

    $.fileDownload(url).done(function () { alert('File download a success!'); });

    I’ve this problem with at least 2 browser : firefox and chrome.

    My application really need this callback… do you know how i can solve my problem ??

    Many thankz for your help !!

    Mickael

  22. Its like you read my mind! Yoou seem to know sso much about this, like you wrote the book inn it or something.
    I think that you can do with a few pics to drive the messge home a litte bit,
    but other than that, this is excellent blog. An excellent read.
    I’ll certainly be back.

  23. I want to try download image file,I try absolute and relative path in my site, but nothing worked

    $.fileDownload('http://www.mysite.com/sites/default/files/toy_images/jpeg/toy-image-1419684403_3170.jpeg')
    .done(function () { alert('File download a success!'); })
    .fail(function () { alert('File download failed!'); });

    or

    $.fileDownload('/sites/default/files/toy_images/jpeg/toy-image-1419684403_3170.jpeg')
    .done(function () { alert('File download a success!'); })
    .fail(function () { alert('File download failed!'); });

    both of them return FAIL to me,where is the problem?

  24. John,

    I need to send back up to a few hundred pairs of field values from a user selection.
    The limitation of going through $.param() is killing me.
    Due to $.param() my model has to be AccountId and DocumentURL, over and over again.
    Even when I get code like this:


    var request =
    [
    {
    name: "EncryptedAccountId",
    value: URLencode("ZuFr1inhsT2gwV8tcYu4dQ==")
    },
    {
    name: "EncryptedUrl",
    value: URLencode("fLFA1GLvRljxk91O4tDnZvoJFt4MClhQZl5SVhC9IeTwUXP8P6yZMGS9UIz9PneoGasaENGFHA3D+Xu7xy0SUoCm8a9LNS9GVbRO246vZEfZf+MyIKwghiZsWDwm1LSQpbO8c8b78gFZkjfYsAKTXgh2eFfP+xqrmmgE8J3AsNjC8WzhwfQyZyttBNuCfMQB4PB+whmLy7nCvrOzVa7q7htCqCFVddPLj2rdsGnvlxqhPuzEX/y6XGpwFaomLfOg+2eQXvKJcn6GS33B9BXObgk8YLmDnjKPWEn3Wgneygeef5YhWNlueMXZyFxsXXvmoMFfLXGLuHU=")
    },
    {
    name: "EncryptedAccountId",
    value: URLencode("ZuFr1inhsT2gwV8tcYu4dQ==")
    },
    {
    name: "EncryptedUrl",
    value: URLencode("fLFA1GLvRljxk91O4tDnZvoJFt4MClhQZl5SVhC9IeTwUXP8P6yZMGS9UIz9PneoGasaENGFHA3D+Xu7xy0SUoCm8a9LNS9GVbRO246vZEfZf+MyIKwghiZsWDwm1LSQpbO8c8b78gFZkjfYsAKTXgh2eFfP+xqrmmgE8J3AsNjC8WzhwfQyZyttBNuCfMQB4PB+whmLy7nCvrOzVa7q7htCqCFVddPLj2rdsGnvlxqhPuzEX/y6XGpwFaomLfOg+2eQXvKJcn6GS33B9BXObgk8YLmDnjKPWEn3Wgneygeef5YhWNlueMXZyFxsXXvmoMFfLXGLuHU=")
    },
    {
    name: "EncryptedAccountId",
    value: URLencode("ZuFr1inhsT2gwV8tcYu4dQ==")
    },
    {
    name: "EncryptedUrl",
    value: URLencode("fLFA1GLvRljxk91O4tDnZvoJFt4MClhQZl5SVhC9IeTwUXP8P6yZMGS9UIz9PneoGasaENGFHA3D+Xu7xy0SUoCm8a9LNS9GVbRO246vZEfZf+MyIKwghiZsWDwm1LSQpbO8c8b78gFZkjfYsAKTXgh2eFfP+xqrmmgE8J3AsNjC8WzhwfQyZyttBNuCfMQB4PB+whmLy7nCvrOzVa7q7htCqCFVddPLj2rdsGnvlxqhPuzEX/y6XGpwFaomLfOg+2eQXvKJcn6GS33B9BXObgk8YLmDnjKPWEn3Wgneygeef5YhWNlueMXZyFxsXXvmoMFfLXGLuHU=")
    }
    ];

    The MVC controller action gets the wrong data submitted.
    I am seeing data like the name of the controller and the name of the action and an null Id coming back.
    I check the network traffic and the expected results are in the Form Data.

    It seems like web technology itself is so disappointing.
    I tried using AJAX. AJAX sends complex JSON data perfectly. But AJAX always wants a response and since my use case is to open up a document the AJAX cannot be used because the byte stream goes to AJAX instead of the browser.

    So I tried the fileDownload but I cannot get the user selected data passed back to the controller. Nothing but heart ache!
    Can you provide any guidance or suggestions or a demo of sending several pairs of values to the server through the fileDownload to a controller action? I use ASP.NET MVC 4.


    [HttpPost]
    public FileResult MergeDocuments(Dictionary mergeRequest)

    Thanks, Joe

    1. Hey Joe,

      Yeah you can’t use “real” AJAX. Not sure, it would be into the specifics of how the model binder is working which I haven’t looked at in a loooong time 🙂

      John

  25. This is my javascript code
    to generate pdf using php dompdf
    I want to download the file after creation / on success of ajax
    I have written following code
    //code—-
    $(“#ExportToPdf”).click(function(){

    // alert($(“#hidden_content”).html());
    var pdfData = $(“#hidden_content”).html();
    var billNo = $(“#hidden_content #billNO”).val();
    //alert(pdfData);
    var billDate = $(“#hidden_content #billdate”).val();
    // alert(billNo+””+billDate);
    bill_name = billNo+”_”+billDate;
    console.log(bill_name);
    $.ajax({
    type:”POST”,
    url:”php/PdfGenerate.php”,
    data:”&data=”+pdfData+”&bill_name=”+bill_name,
    success:function(data){
    console.log(‘”pdf\/bill_’+bill_name+’.pdf”‘);
    var path = “pdf/bill_2_2015-03-26.pdf”;
    //console.log($.fileDownload(“pdf/bill_”+bill_name+”.pdf”));
    $.fileDownload(path,{
    contentType: “application/pdf”
    })
    .done(function () { alert(‘File download a success!’); })
    .fail(function () { alert(‘File download failed!’); });
    console.log(“pdf has been genrated “);
    // console.log(data);
    },
    error:function(){
    alert(‘error’);
    }

    });

    });

    file fail to download and show following error on console

    Resource interpreted as Document but transferred with MIME type application/pdf: “http://localhost/pathology_app/pdf/bill_2_2015-03-26.pdf”.

    please give solution as early as possible
    Thanking U!!!

    1. Hi,
      Love this plugin, but having an issue with getting the error in the failCallback. Error comes as undefined when I use this in my code:

      failCallback: function (responseHtml, url, error) {
      console.log(error);
      }

      I think it’s because the plugin code isn’t passing back the error:

      internalCallbacks.onFail(formDoc.body.innerHTML, fileUrl);

      Is there any way to get the error passed back in this case in the fail callback, so it can be handled appropriately?

  26. Hello John.
    Congratulations for their work!

    I’d like sugest that on the callback functions
    accept as JSON response from back-end.

    Example: .done(function (resultParam){}

    Or

    let the developer choose

    Example: .done(function (resultParam){
    //code to part to html here.
    //code to part to json here.
    }

    Some times the server need to send errors messages to client (a real error message not a generic error message).

  27. Hi John!

    I’m trying to use your plugin for download dynamically generated file from server!
    But my server require custom request header token to accept request!
    So I must do it how ?

    Thanks for reply and have a nice day…

  28. Hai,

    I want to try download image file nothing working reply!!!..

    $.fileDownload(“images/images.jpg”)
    .done(function () { alert(‘File download a success!’); })
    .fail(function () { alert(‘File download failed!’); });

    1. image download not working.,..

      $(document).on(“click”, “a.fileDownloadLink”, function () {
      $.fileDownload(“../images/images.jpg”)
      .done(function () { alert(‘File download a success!’); })
      .fail(function () { alert(‘File download failed!’); });
      });

  29. ポストをありがとうございましたあなたのサイトと私は話題に興味を持つようになりました。私はあなたのコンテンツが好きで、私は私が私の仕事であなたの言葉を使うことができるかどうかを考えていますか?それはそうなのでしょうか?はい場合は、私と連絡してください。ありがとうございます。すべての

  30. Hi,
    Love this plugin, but having an issue with getting the error in the failCallback. Error comes as undefined when I use this in my code:

    failCallback: function (responseHtml, url, error) {
    console.log(error);
    }

    I think it’s because the plugin code isn’t passing back the error:

    internalCallbacks.onFail(formDoc.body.innerHTML, fileUrl);

    Is there any way to get the error passed back in this case in the fail callback, so it can be handled appropriately?

  31. Could not get the completion callbacks to run.
    Both the done callback and the successCallback would not run.
    Reduced it back to the simplest case possible running in an asp.net mvc app.
    Not sure why it’s not running callbacks. Everything else works Ok. May still use it, can’t find anything better.

Leave a Reply

Your email address will not be published. Required fields are marked *

Proudly powered by WordPress | Theme: Cute Blog by Crimson Themes.