47

In our application we need to implement following scenario:

  1. A request is send from client
  2. Server handles the request and generates file
  3. Server returns file in response
  4. Client browser displays file download popup dialog and allows user to download the file

Our application is ajax based application, so it would be very easy and convenient for us to send ajax request (like using jquery.ajax() function).

But after googilng, it turned out that file downloading is possible only when using non-ajax POST request (like described in this popular SO thread). So we needed to implement uglier and more complex solution that required building HTML structure of form with nested hidden fields.

Could someone explain in simple words why is that ajax requests cannot be used to download file? What's the mechanics behind that?

Community
  • 1
  • 1
Piotr Sobczyk
  • 6,015
  • 6
  • 42
  • 65
  • 3
    this is due the fact, that everything retrieved via AJAX goes into javascript "memory". And you dont want the file in javascript memory, so your best bet should be http://stackoverflow.com/questions/3502267/download-a-file-using-ajax (BalusC's answer) – Najzero Feb 04 '13 at 08:04
  • 1
    [Wikipedia](http://en.wikipedia.org/wiki/Ajax_(programming)): `...retrieve data from, a server asynchronously without interfering with the display and behavior of the existing page.` So it won't interfere with the page and the data will only being stored in the JavaScript memory space. – Derek 朕會功夫 Feb 04 '13 at 08:12
  • possible duplicate of [Handle file download from ajax post](http://stackoverflow.com/a/23797348/148271) – IsmailS Jan 19 '15 at 15:14

4 Answers4

59

It's not about AJAX. You can download a file with AJAX, of course. However the file will be kept in memory, i.e. you cannot save file to disk. This is because JavaScript cannot interact with disk. That would be a serious security issue and it is blocked in all major browsers.

freakish
  • 48,318
  • 8
  • 114
  • 154
  • 7
    This does not seem to be correct, since you can use Blob to save the file, like e.g. here: http://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link, and this does not seem like a security issue since it's not direct interaction but only telling browser to download file from memory rather than from server. – Ilya Chernomordik Jul 17 '15 at 13:55
  • How is it different from `window.location = urlWhereFileCanBeDownloaded`, which serves a file anyways, thereby allowing JS a way to circumvent all of this? – Alexandru Apr 26 '16 at 19:22
3

This can be done using the new HTML5 feature called Blob. There is a library FileSaver.js that can be utilized as a wrapper on top of that feature.

Ilya Chernomordik
  • 20,693
  • 15
  • 84
  • 144
1

That's the same question I'd asked myself two days ago. There was a project with client written using ExtJS and server side realisation was on ASP.Net. I have to translate server side to Java. There was a function to download an XML file, that server generates after Ajax request from the client. We all know, that it's impossible to download file after Ajax request, just to store it in memory. But ... in the original application browser shows usual dialog with options open, save and cancel downloading. ASP.Net somehow changed the standard behaviour... It takes me two day to to prove again - there is no way to download file by request usual way ... the only exception is ASP.Net... Here is ASP.Net code

public static void WriteFileToResponse(byte[] fileData, string fileName)
    {
        var response = HttpContext.Current.Response;

        var returnFilename = Path.GetFileName(fileName);
        var headerValue = String.Format("attachment; filename={0}", 
            HttpUtility.UrlPathEncode(
                String.IsNullOrEmpty(returnFilename) 
                    ? "attachment" : returnFilename));
        response.AddHeader("content-disposition", headerValue);
        response.ContentType = "application/octet-stream";
        response.AddHeader("Pragma", "public");

        var utf8 = Encoding.UTF8;
        response.Charset = utf8.HeaderName;
        response.ContentEncoding = utf8;
        response.Flush();
        response.BinaryWrite(fileData);
        response.Flush();
        response.Close();
    }

This method was called from WebMethod, that, in turn, was called from ExtJS.Ajax.request. That's the magic. What's to me, I've ended with servlet and hidden iframe...

bes67
  • 223
  • 1
  • 3
  • 8
-3

you can do this by using hidden iframe in your download page

just set the src of the hidden ifame in your ajax success responce and your task is done...

  $.ajax({
        type: 'GET',
        url: './page.php',
        data: $("#myform").serialize(),
        success: function (data) {
          $("#middle").attr('src','url');
        },

});
Sanoob
  • 2,328
  • 3
  • 26
  • 34