Binary files corrupted - How to Download Binary Files with AngularJS

How to Download Binary Files with AngularJS

When downloading binary files, it is important to set the responseType:

app.service('VerDocServices',['$http',function($http) {

    this.downloadFile = function(url, file, urlDir) {
        var config = {
            //SET responseType
            responseType: 'blob',
            params : {
                file : file,
                urlDir : urlDir
            }
         };

        return $http.get(url, config)
          .then(function(response) {
            return response.data;
        }).catch(function(response) {
            console.log("ERROR: ", response.status);
            throw response;
        }); 
    }; 
}]);

If the responseType is omitted the XHR API defaults to converting UTF-8 encoded text to DOMString (UTF-16) which will corrupt PDF, image, and other binary files.

For more information, see MDN Web API Reference - XHR ResponseType


I don't know much about the backend, but I'll provide what i have used may be it will help, so On the Java Script File:

//your $http(request...)

.success(function (data, status, headers, config) {
  //Recieves base64 String data
  var fileName = 'My Awesome File Name'+'.'+'pdf';

  //Parsing base64 String...
  var binaryString =  window.atob(data);
  var binaryLen = binaryString.length;
  var fileContent = new Uint8Array(binaryLen);
  for (var i = 0; i < binaryLen; i++)        {
     var ascii = binaryString.charCodeAt(i);
     fileContent[i] = ascii;
  }
  var blob = new Blob([fileContent], { type: 'application/octet-stream' }); //octet-stream
  var fileURL = window.URL.createObjectURL(blob);
  $sce.trustAsResourceUrl(fileURL);  //allow angular to trust this url
  //Creating the anchor download link
  var anchor = angular.element('<a/>');
  anchor.css({display: 'none'}); // Make sure it's not visible
  angular.element(document.body).append(anchor); // Attach it to the document
  anchor.attr({
    href: fileURL,
    target: '_blank',
    download: fileName
  })[0].click();
  anchor.remove(); // Clean it up afterwards
})
//.error(function(...

And On your backend, make sure that your webservice produces octet-stream and returning the file in base64 data format, i did this using Java JAX-RS like this:

@POST
@Path("/downloadfile")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(...){
  String base64String = Base64.getEncoder().encodeToString(/*here you pass your file in byte[] format*/);
  return Response.ok(base64String).build();
}