我正在尝试从我的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:object
$ resolved:true`
为什么angularjs中收到的content
包含字符
已经而不是一个字节的数组?
如何以我只会使用的方式控制content
csv相关数据并删除$promise
和$resolved
?它们为什么首先包括在内?如何删除它们?
如果我正在做的是什么,生成csv的正确方法是什么 错误? :|
答案 0 :(得分:5)
忘了更新这个,但我现在找到了解决这个问题的方法:
将有两个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控制器:
GET:
[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
会导致浏览器自动下载文件,询问您是否保存文件。
答案 1 :(得分:0)
我是这样做的:(用铬测试)
// 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();
}
}
});
包含它可以帮助其他人。