[英]generate csv from mvc web api httpresponse and receive it by angularjs for download
我試圖從我的web api生成一個CSV文件,並通過angularjs接收該文件。 我有一個如下所示的API控制器:
[HttpPost]
public HttpResponseMessage GenerateCSV(FieldParameters fieldParams)
{
var output = new byte[] { };
if (fieldParams!= null)
{
using (var stream = new MemoryStream())
{
this.Serialize(fieldParams, stream);
stream.Flush();
output = stream.ToArray();
}
}
var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(output) };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Fields.csv"
};
return result;
}
在我的angularjs中,我有這個:
$scope.save = function () {
var csvInput= extractDetails();
// File is an angular resource. We call its save method here which
// accesses the api above which should return the content of csv
File.save(csvInput, function (content) {
console.log(content);
// only creates a csv file with "[object Object]" written in it
var hiddenElement = document.createElement('a');
hiddenElement.href = 'data:text/csv;charset=utf-8,\uFEFF' + encodeURI(content.Parameters);
hiddenElement.target = '_blank';
hiddenElement.download = 'myFile.csv';
hiddenElement.click();
});
};
讓我們舉例來說,在我的API控制器中,響應的內容是
產量
{字節[152]}
[0]:83
[1]:101
[2]:44
[3]:67
[4]:10
當我在angularjs中收到這個並且我將content
的值放在控制台日志(chrome)中時,這就是我得到的:
{Parameters:Array [1],$ promise:Object,$ resolved:true,$ get:function,$ save:function ...}
0: “S”
1:“e”
2:“,”
3:“C”
4:“↵”
$ promise:對象
$ resolved:true`
為什么angularjs中收到的content
已包含字符而不是數組的字節?
如何以這樣的方式控制content
:我只使用csv相關數據並刪除$promise
和$resolved
? 它們為什么首先包括在內? 如何刪除它們?
如果我正在做的事情是錯誤的,那么生成csv的正確方法是什么? :|
忘了更新這個,但我現在找到了解決這個問題的方法:
將有兩個API,一個(POST)將記住要在處理中使用的數據,另一個(GET)將分配文件。
POST:
[HttpPost]
public async Task<HttpResponseMessage> BuildFile(FileParameters fileParams)
{
var guid = Guid.NewGuid().ToString();
if (fileParams!= null)
{
await Task.Run(() => FileContents.Add(guid, fileParams));
return this.Request.CreateResponse(HttpStatusCode.OK, new { Value = guid });
}
return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid data");
}
在AngularJs中,記住guid返回並將其傳遞給另一個api:
location.href = '/api/file/generatefile' + '?guid=' + generatedGuidFromAPI + '&reportName=' + $scope.reportName;
這是MVC中的generatefile
API控制器:
得到:
[HttpGet]
public async Task<HttpResponseMessage> GenerateFile(string guid, string reportName)
{
byte[] output = null;
if (FileContents.ContainsKey(guid))
{
await Task.Run(() =>
{
using (var stream = new MemoryStream())
{
this.CreateFile(FileContents[guid], stream);
stream.Flush();
output = stream.ToArray();
}
});
}
FileContents.Remove(guid);
if (output != null)
{
var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(output) };
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = reportName + ".csv"
};
return result;
}
return this.Request.CreateErrorResponse(HttpStatusCode.NoContent, "No record found");
}
使用location.href
將導致瀏覽器自動下載文件,詢問是否保存。
我是這樣做的:(用鉻測試)
// WebAPI controller action
public IHttpActionResult Get(string rpt, DateTime date)
{
List<DailyMIReportViewModel> list = new List<DailyMIReportViewModel>();
// Do some stuff to generate list of items
// Download Requested
if (rpt == "dailymidl")
{
// Create byte array of csv
byte[] csvData = WriteCsvWithHeaderToMemory(list);
// create FileContentResult of cdv byte array
FileContentResult result = new FileContentResult(csvData, "application/octet-stream");
// set filename in FileContentResult
result.FileDownloadName = "Report.csv";
return Ok(result);
}
// Data Requested
return Ok(list);
// Client-side angularjs
// Called on button click
$scope.generateMIDownload = function (forDate) {
// Using $resource to return promise with FileContentResult payload
reportsRepository.dailymidl(forDate).$promise.then(
function (data) {
//ok
// NOTE: the base64 part is what got it working
var dataUrl = 'data:application/octet-stream;base64,' + data.FileContents
var link = document.createElement('a');
angular.element(link)
.attr('href', dataUrl)
.attr('download', data.FileDownloadName)
.attr('target','_blank')
link.click();
},
function (response) {
//not ok
});
}
// Reports Repository (for ref)
angular.module('msgnr').factory('reportsRepository', function ($resource) {
return {
dailymidl: function (date) {
return $resource('/api/Report/', { rpt: 'dailymidl', date: date, toDate: date }).get();
}
}
});
包括它可以幫助其他人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.