2016-12-04 27 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

感謝您的幫助,但它並沒有解決問題... –

相關問題