0

I have services like this

@POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/reports")
public Response exportCSV(Map<String,List<String>> criteria) {


    Response response = null;
    if (userId != null) {
        response = Response 
                .ok("Test Data".toByteArray(), MediaType.APPLICATION_OCTET_STREAM)
                .header("Content-Disposition", 
                        "attachment; filename=\"Sample_report.csv\"")
                .build();
    } else {
        response = Response.noContent().build();
    }
    return response;
}

and my UI side code is

var exportService = new Downloadreport ();
exportService.exportReport();

and Downloadreport code looks like this

define([
    'backbone'
], function(
    Backbone
){
    var Downloadreport = Backbone.Model.extend({
        url: 'http://localhost:8080/services/reports',

        exportReport: function() {
            this.save({}, {
                data: JSON.stringify("Some valid test data"),
                dataType: 'text',
                contentType: 'application/json',
                type: 'POST',
                success: function(model, response){
                 // Create a new Blob object using the 
                 //response data of the onload object
                 var blob = new Blob([response], {type: 'text/csv'});
                 //Create a link element, hide it, direct 
                 //it towards the blob, and then 'click' it programatically
                 let a = document.createElement("a");
                 a.style = "display: none";
                 document.body.appendChild(a);
                 //Create a DOMString representing the blob 
                 //and point the link element towards it
                 let url = window.URL.createObjectURL(blob);
                 a.href = url;
                 a.download = 'Sample_report.csv';
                 //programatically click the link to trigger the download
                 a.click();
                 //release the reference to the file by revoking the Object URL
                 window.URL.revokeObjectURL(url);
            } 
            });
            console.log("POSTing stuff");
        }
    });

    return Downloadreport;
});

When i test my UI, i see correct response is coming(I can see that in Response header of my http POST request). But i expect a CSV file downloaded. which is not happening. When i test my service with Adv REST client also, i see the response correctly, though i am not sure if file download can be tested with REST client. Any help is appreciated

UPDATE2: I managed fix this by adding success call back and instructing the browser to download it. Is this a right way to do this? Does the above approach save the file content in browser? is this approach harmful for bigger downloads?

user2555212
  • 165
  • 1
  • 14
  • You can't reliably start a download with an AJAX request. You'll have to send back a link to redirect to. – Emile Bergeron Jan 22 '18 at 04:02
  • thanks Emile for the response. with a call back i managed to download. updated the code with callback. is that a good approach? – user2555212 Jan 25 '18 at 09:21
  • That's what I meant with reliability, you found the unreliable way to do it. It'll work for some, but won't for others. [There are plenty of hacks](https://stackoverflow.com/q/16086162/1218980) but none that work for everyone. – Emile Bergeron Feb 01 '18 at 02:41

1 Answers1

0

UPDATE2: I managed fix this by adding success call back and instructing the browser to download it. Is this a right way to do this? Does the above approach save the file content in browser? is this approach harmful for bigger downloads?

here is the callback code.

   success: function(model, response){
                     // Create a new Blob object using the 
                     //response data of the onload object
                     var blob = new Blob([response], {type: 'text/csv'});
                     //Create a link element, hide it, direct 
                     //it towards the blob, and then 'click' it programatically
                     let a = document.createElement("a");
                     a.style = "display: none";
                     document.body.appendChild(a);
                     //Create a DOMString representing the blob 
                     //and point the link element towards it
                     let url = window.URL.createObjectURL(blob);
                     a.href = url;
                     a.download = 'Sample_report.csv';
                     //programatically click the link to trigger the download
                     a.click();
                     //release the reference to the file by revoking the Object URL
                     window.URL.revokeObjectURL(url);
                }
user2555212
  • 165
  • 1
  • 14