2016-12-04 74 views
0

所以我有一个问题,当我试图从服务器响应保存文件。javascript保存HTTP响应文件(Web Api HttpResponseMessage)

当我尝试从我的浏览器中的url下载文件时,所有的工作,但是当我试图从clint端发送请求文件被保存,但在文件中有“[对象对象]”,如果它是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; 
    } 

在这里,我的克林特代码:

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

如果您尝试下载文件。你的头文件必须有** content-type:multipart/form-data **。如果您无法正确打开PDF文件,则表示该流受到影响。所以你需要弄清楚转换 – Aravind

回答

0

服务器代码显然是在响应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头中的文件名,并创建从所述响应数据的斑点。它将<a>标记的download属性设置为文件名的值,将href属性设置为blob的值。点击<a>将导致浏览器打开保存对话框。

0

如果数据在json格式中,你可以使用这个

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

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

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

感谢您的帮助,但它并没有解决问题... –