本文介绍了javascript从http响应保存文件(Web Api HttpResponseMessage)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,当我尝试从服务器响应中保存文件时遇到问题.

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

当我尝试从浏览器中的url下载文件时,所有工作正常,但是当我尝试从clint端发送请求时,文件已保存,但文件中存在"[Object object]",并且如果是PDF文件无法打开.

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.

请求中必须包含一个附加标头,其中包含客户端的密钥ID.

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

这是我的服务器代码:

        [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;
    }

这是我的克林特代码:

 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();
    })

推荐答案

服务器代码显然正在发送二进制数据,以响应来自客户端的HTTP GET.在这种情况下,客户端需要将XHR设置为 responseType:arraybuffer .

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.

示例HTML

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

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

HTML创建两个按钮.单击第一个按钮可从服务器获取文件.第二个按钮保存文件.

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

xd-href 指令

xd-href Directive

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

该指令监视由 xd-href 属性定义的scope属性,并将 href 属性设置为该scope属性的值.

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

控制器

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;
     });
};

控制器使用XHR GET方法获取文件,从 Content-Disposition 标头中提取文件名,并从响应数据中创建blob.它将< a> 标记的 download 属性设置为文件名的值,并将 href 属性设置为blob的值.单击< a> 将使浏览器打开一个保存对话框.

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.

这篇关于javascript从http响应保存文件(Web Api HttpResponseMessage)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 07:36