【问题标题】:javascript save file from http response (Web Api HttpResponseMessage)javascript保存来自http响应的文件(Web Api HttpResponseMessage)
【发布时间】:2016-12-04 11:44:27
【问题描述】:

所以当我尝试从服务器响应中保存文件时遇到问题。

当我尝试从浏览器中的 url 下载文件时,一切正常,但是当我尝试从 clint 端发送请求时,文件被保存,但文件中有“[Object object]”,如果它是 PDF 文件打不开。

请求必须包含一个包含客户端密钥 ID 的附加标头。

这是我的服务器代码:

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

这里是我的 clint 代码:

 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) {

    });

另外,我还尝试了以下代码:

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

【问题讨论】:

  • 如果您正在尝试下载文件。您的标头必须具有 content-type:multipart/form-data 。如果您无法正确打开 pdf 文件,则表示流受到影响。所以你需要在转化中弄清楚

标签: javascript .net angularjs


【解决方案1】:

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

示例 HTML

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

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

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

xd-href 指令

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

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

控制器

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。它将&lt;a&gt; 标记的download 属性设置为文件名的值,并将href 属性设置为blob 的值。点击&lt;a&gt;会导致浏览器打开保存对话框。

【讨论】:

    【解决方案2】:

    如果数据是json格式的可以用这个

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

    或者你也可以用它来编码你的数据,试试这个

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 1970-01-01
      • 2012-11-06
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      相关资源
      最近更新 更多