0

I have a http service which returns a HTTP response of type

Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

and if I call this HTTP service from curl and redirect I get the .xlsx file recreated correctly. However trying to save the file from javascript fails. The code that I am using:

cURL:

$ curl -v -X POST <API_ENDPOINT> > a.xlsx ;# a.xlsx works fine

Javascript:

$http.post(<API_ENDPOINT>).then(function(response) {
          console.log(response);
          downloadFile(response.data, "b.xlsx")
});

var downloadFile = function(responseData, fileName) {
      var blob = new Blob([responseData], {
        type: 'application/vnd.ms-excel'
      });

      if (window.navigator.msSaveOrOpenBlob) {
          window.navigator.msSaveBlob(blob, fileName);
      } else {
        var a = document.createElement('a');
        var url = window.URL.createObjectURL(blob);

        document.body.appendChild(a);
        a.style = 'display: none';
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
        document.body.removeChild(a);
      }
};

The file is saved, however the contents seem to be different from the curl one, even though the server is sending the same file.

The content-length header value is the same for both the responses (curl and javascript (captured via chrome devtools)) but the filesize when redirected via curl is 5.1k (almost same as the content-length value) but the the filesize of file created via js, is 8.5k and is wrong.

I've tried setting application/octet-stream, octet/stream, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet while creating the blob and none of that helps.

I think I am messing up something in content-type and the blob creation but not able to figure out what is wrong. Any help ?

3
  • 1
    why bother using AJAX to download a file, since you then have to get a blob object and create a fake hyperlink in order to get it to actually download? You could just use window.location or window.open and access the download URL directly (although the endpoint would have to respond to a GET rather than a POST, but semantically that makes more sense anyway since youre _get_ting a file, not sending any data to the server). AJAX is inherently not suited to file downloads. Commented Aug 28, 2018 at 11:43
  • It needs to be a POST and not a GET because of some other parameters that I need to pass along with the call which will result in a db update of some kind. I have cleaned out all those business logic specific code and gave this code for brevity. Commented Aug 28, 2018 at 11:50
  • 1
    in that case you might be better to submit a hidden form via POST. Or, get your initial AJAX POST request to simply return a URL which can then be visited with GET to actually retrieve the file. Commented Aug 28, 2018 at 12:10

1 Answer 1

1

I have figured out the problem. The $http.post method needs another parameter to be set if the response type is going to be binary. The change that I had to make is:

$http.post(<API_ENDPOINT>, null, {responseType: 'arraybuffer'});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.