2

So i have a problem when i tried to save file from server response.

When i try to download the file from url in my browser all work but when i tried to send request from the clint side the file is saved but in the file there is "[Object object]" and if it's a PDF file does not open.

The request must include an additional header that contains the key ID of the client.

Here my server code :

        [HttpGet, IsAllowed(4,PageAction.Download)]
    public HttpResponseMessage Download(string id)
    {
        var path = HttpContext.Current.Server.MapPath("~") + string.Format(@"Files\{0}.doc",id);
        var stream = new FileStream(path, FileMode.Open);
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");            
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        result.Content.Headers.ContentDisposition.FileName = string.Format("{0}.doc", id);
        return result;
    }

And here my clint code :

 function get() {
    var defer = $q.defer();

    $http.post('http://localhost:4704/api/file/download/1', { responseType: 'arrayBuffer' }).then(
        function (data, status, headers, config) {
            var results = {
                data: data,
                headers: data.headers(),
                status: data.status,
                config: data.config
            };
            defer.resolve(results);

        }, function (data, status, headers, config) {
            defer.reject(data);
        });
    return defer.promise;
}


$scope.download = function () {

    get().then(function (response) {
        var octetStreamMime = 'application/octet-stream';
        var fileName = "Test.doc";
        var contentType = response.headers["content-type"] || octetStreamMime;
        try {
            var blob = new Blob([response.data], { type: contentType });
            if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                window.navigator.msSaveOrOpenBlob(blob, fileName);
            } else {
                var objectUrl = URL.createObjectURL(blob);
                window.open(objectUrl);
            }
        } catch (exc) {
            console.log("Save Blob method failed with the following exception.");
            console.log(exc);
        }

    }, function (error) {

    });

In addition, I also tried the following code:

    $http.get("http://localhost:4704/api/file/download").then(function (res) {
        var anchor = angular.element('<a/>');
        anchor.attr({
            href: 'data:attachment/doc;charset=utf-8,',
            target: '_blank',
            download: 'test.doc'
        })[0].click();
    })
1
  • if you are trying to download a file . ur header must have content-type:multipart/form-data . If you are not able to open the pdf file properly, it means that the stream is affected. so you need to figure out in the conversions Commented Dec 4, 2016 at 12:22

2 Answers 2

1

The server code is clearly sending binary data in response to an HTTP GET from the client. In that case the client needs to set the XHR to responseType: arraybuffer.

Example HTML

<button ng-click="fetch()">Get file</button>

<a download="{{filename}}" xd-href="data">
  <button>SaveAs {{filename}}</button>
</a>

The HTML creates two buttons. Clicking the first button gets the file from the server. The second button saves the file.

xd-href Directive

app.directive("xdHref", function() {
  return function linkFn (scope, elem, attrs) {
     scope.$watch(attrs.xdHref, function(newVal) {
       newVal && elem.attr("href", newVal);
     });
  };
});

The directive watches the scope property defined by the xd-href attribute and sets the href attribute to the value of that scope property.

Controller

var url = "http://localhost:4704/api/file/download/1";
$scope.fetch = function() {
     $http.get(url, {responseType: "arraybuffer"})
       .then (function (response) {
         var disposition = response.headers("content-disposition");
         var filename = disposition.match(/filename="(\w*.\w*)"/)[1];
         $scope.filename = filename || "f.bin";
         $scope.data = new Blob([response.data]);
     }).catch(function (error) {
         console.log(error);
         throw error;
     });
};

The controller uses an XHR GET method to fetch the file, extracts the filename from the Content-Disposition header, and creates a blob from the response data. It sets download attribute of the <a> tag to the value of the file name and the href attribute to the value of the blob. Clicking on the <a> will cause the browser to open a save dialog box.

Sign up to request clarification or add additional context in comments.

Comments

0

If the data is in json format you can use this

href: 'data:text/plain;charset=utf-8,' + JSON.stringify(data)

or you can also use this to encode your data,try this

href: 'data:text/plain;charset=utf-8,' + encodeURIComponent(data)

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.