Stephane
Stephane

Reputation: 12810

Download a zip file in AngularJS

Trying to have a zip file download in AngularJS I looked at AngularJS: download pdf file from the server and coded my controller as:

  RolloutService.export(rollout.id, function(data, status, headers) {
    var headers = headers();
    var filename = headers['download-filename'] || 'file';
    var octetStreamMime = 'application/octet-stream';
    var contentType = headers['Content-Type'] || octetStreamMime;
    if (navigator.msSaveBlob) {
      var blob = new Blob([data], { type: contentType });
      navigator.msSaveBlob(blob, filename);
    } else {
      var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
      if (urlCreator) {
        var link = document.createElement("a");
        if ("download" in link) {
          var blob = new Blob([data], { type: contentType });
          var url = urlCreator.createObjectURL(blob);
          link.setAttribute("href", url);
          link.setAttribute("download", filename);
          var event = document.createEvent('MouseEvents');
          event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
          link.dispatchEvent(event);
        } else {
          var blob = new Blob([data], { type: octetStreamMime });
          var url = urlCreator.createObjectURL(blob);
          window.location = url;
        }
      }
    }
  });

But my file comes partly only.

Trying to unzip it gives:

stephane@stephane-ThinkPad-X60:~> unzip -l file
Archive:  file
error [file]:  missing 96319383 bytes in zipfile
  (attempting to process anyway)
error [file]:  start of central directory not found;
  zipfile corrupt.

Note that if skipping the controller and going for a direct window.open() then the file comes complete and can be unzipped.

On the controller export request, the browser console shows the following headers:

Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/nitro-project-rest/rollouts/2/export
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en
Authorization:Basic bnNuQG5zbi5jb206ZXRvaWxl
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/34.0.1847.116 Chrome/34.0.1847.116 Safari/537.36
Response Headers
Access-Control-Allow-Headers:Accept-Language,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
Access-Control-Allow-Methods:POST, PUT, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:9000
Access-Control-Max-Age:3600
Cache-Control:no-store
Cache-Control:no-cache
Content-Disposition:attachment; filename="Orange-rollout-rollout-export.zip"
Content-Length:1960
Content-Type:application/zip
Date:Wed, 05 Nov 2014 20:33:31 GMT
download-filename:Orange-rollout-rollout-export.zip
Expires:Thu, 01 Jan 1970 00:00:00 GMT
Pragma:no-cache
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

Upvotes: 2

Views: 12630

Answers (1)

Stephane
Stephane

Reputation: 12810

My $http service was corrupting the file when sending the request.

I needed to add the following configuration:

responseType: 'arraybuffer'

as in:

factory.rolloutExport = function(rolloutId, successCallback, failureCallback) {
      $http({
        url: ENV.NITRO_PROJECT_REST_URL + '/rollouts/' + rolloutId + '/export',
        method: 'GET',
        responseType: 'arraybuffer',
        cache: false,
        headers: {
          'Content-Type': 'application/json; charset=utf-8',
          'Authorization': AuthService.getCredentialsHeaders()
        }
      }).success(successCallback).error(failureCallback);
    };

Now the zip file comes back untouched by any encoding converter.

Upvotes: 4

Related Questions