0

I have an application that contains a grid and button for the user to be able to export the grid to excel. I want to be able to show the save as dialog box when the server responds with the excel file.The server accepts the parameters as a JSON object. Here is my code:-

Ext.Ajax.request({
   url: '/export/excel/',
   method: 'POST',
   //Send the query as the message body
   jsonData: jsonStr,
   success: function (result,request) {
        Ext.DomHelper.append(document.body, {
           tag: 'iframe',
            frameBorder: 0,
            width: 0,
            height: 0,
            //src:result,
            css: 'display:none;visibility:hidden;height:1px;'
        });
    }, //success
    failure: function (response, opts) {
        var msg = 'server-side failure with status code: ' + response.status + ' message: ' + response.statusText;
        Ext.Msg.alert('Error Message', msg);
    }
});

I know there is a similar question ( ExtJS AJAX save as dialog box) but that references a static file on the server.In my case, depending upon the json sent the result is going to be different each time. I get back the entire excel file that i want in the result.responseText. What needs to be done so that the dialog box popup up asking the user for save as options? Also, im not sure how the src in the domhelper should be configured. Any help would be really appreciated.

Community
  • 1
  • 1
Armaan
  • 205
  • 10
  • 21

2 Answers2

2

I believe the only way to do this in a totally client agnostic way is to force it from the server-side using a Content-Type of: octect-stream and Content-Disposition of 'attachment' with a suggested filename. See:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1

and

http://www.ryboe.com/tutorials/php-headers-force-download

You can also use so-called 'dataURIs' but they have their own set of issues:

http://en.wikipedia.org/wiki/Data_URI_scheme

My recommendation would be to return EXCEL content dynamically on the server and just make the button a link to that url that POSTS the current data your working with and sets the correct response headers to trigger your browser to download the file. Since you are doing an AJAX call and not letting the web-browser get the URL directly, any HTTP headers you set to control the way the browser interprets the content won't matter because you are doing it in JS not in the user's browser. By returning the content directly to the user through a link on the server, you'll get around this problem.

Since you actually want the user to click on the link, I don't think AJAX is appropiate here.

omnisis
  • 1,208
  • 8
  • 9
  • The server side is already working fine and returning the excel file that i want with the exact headers that you mentioned, its just the dialog box that i want.How would i be able to post the JSON data from the button since the content-type needs to `'application/json'`? – Armaan Apr 22 '12 at 22:51
  • Also the JSON is built in the event handler for the export button which is also where the code i posted in the question lies. The JSON data needs to be constructed each time the export button gets clicked since there are two tab panels that each contain grids and based on the active tab the json gets built with certain parameters selected for building that grid in the first place. – Armaan Apr 22 '12 at 22:56
  • If I am understanding correctly you need to pull data off a specific grid component's store then post as JSON to get back a response of octet-stream or what-have-you. So for the first part use Ext.Store.getRange which hands back instance of Model objects and use the params option to your outgoing Ajax request to set those recs as a parameter in your request JSON. see also: http://stackoverflow.com/questions/2526764/how-to-retrieve-json-data-array-from-extjs-store and http://stackoverflow.com/questions/2917581/how-to-post-json-data-with-extjs – omnisis Apr 23 '12 at 13:49
  • +1 thanks for your help, i took a slightly different approach and changed things around on the server side. Instead of returning the file as an attachment i just sent back the path and used that as the source of the iframe. – Armaan Apr 24 '12 at 19:11
1

I made the server side return the path of the location the file is created and saved, instead of sending the file as an attachment in the response and hence avoiding the problem of setting the headers in the response. Then i just set the source of the iframe in the code to the path that gets returned in the response (result.responseText).

Armaan
  • 205
  • 10
  • 21