从Web API中使用AngularJS下载CSV文件
从Web API中使用AngularJS下载CSV文件
我的API控制器返回一个CSV文件,如下所示:
[HttpPost] public HttpResponseMessage GenerateCSV(FieldParameters fieldParams) { var output = new byte[] { }; if (fieldParams != null) { using (var stream = new MemoryStream()) { this.SerializeSetting(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 = "File.csv" }; return result; }
我使用AngularJS发送和接收CSV文件的代码如下:
$scope.save = function () { var csvInput = extractDetails(); // File是一个Angular资源。我们在这里调用它的save方法,访问上面的API,该API应该返回CSV的内容 File.save(csvInput, function (content) { var dataUrl = 'data:text/csv;utf-8,' + encodeURI(content); var hiddenElement = document.createElement('a'); hiddenElement.setAttribute('href', dataUrl); hiddenElement.click(); }); };
在Chrome浏览器中,它会下载一个名为“document”的文件,但没有文件类型扩展名。
文件内容为`[Object object]`。
在IE10中,没有下载任何内容。
我该如何修复这个问题?
更新:
这个链接可能对有相同问题的人有用:[链接](https://stackoverflow.com/questions/20303988/generate-csv-from-mvc-web-api-httpresponse-and-receive-it-by-angularjs-for-downl/20917641#20917641)
问题:在AngularJS中如何从Web API下载CSV文件?
原因:在AngularJS中,由于浏览器的兼容性问题,直接从Web API下载CSV文件可能会遇到一些困难。
解决方法:以下是一种解决方法,可以通过创建一个临时链接来下载CSV文件:
if (window.navigator.msSaveOrOpenBlob) { var blob = new Blob([decodeURIComponent(encodeURI(result.data))], { type: "text/csv;charset=utf-8;" }); navigator.msSaveBlob(blob, 'filename.csv'); } else { var a = document.createElement('a'); a.href = 'data:attachment/csv;charset=utf-8,' + encodeURI(result.data); a.target = '_blank'; a.download = 'filename.csv'; document.body.appendChild(a); a.click(); }
以上解决方法可以通过判断浏览器是否支持`msSaveOrOpenBlob`方法来选择不同的下载方式。如果浏览器支持该方法,则创建一个Blob对象并通过`navigator.msSaveBlob`保存或打开该Blob对象;否则,创建一个``标签,并设置其href为CSV文件的数据,target为`_blank`,download为文件名,然后将该``标签添加到页面中并点击该链接以触发文件下载。
通过以上解决方法,我们可以在AngularJS中从Web API下载CSV文件。
问题:在Chrome 42中,无法通过AngularJS从Web API中下载CSV文件。
原因:在Chrome 42中,使用传统的下载方式无法下载CSV文件,需要使用base64编码的方式来下载文件。
解决方法:通过在AngularJS的指令中使用base64编码的方式来下载文件。
具体实现如下:
link: function(scope, element, attrs) { var downloadFile = function downloadFile() { var filename = scope.getFilename(); var link = angular.element('<a/>'); link.attr({ href: 'data:attachment/csv;base64,' + encodeURI($window.btoa(scope.csv)), target: '_blank', download: filename })[0].click(); $timeout(function(){ link.remove(); }, 50); }; element.bind('click', function(e) { scope.buildCSV().then(function(csv) { downloadFile(); }); scope.$apply(); }); }
以上代码通过在指令的link函数中定义了一个downloadFile函数来实现文件下载。首先获取要下载的文件名,然后创建一个a标签元素,设置其href属性为base64编码的CSV文件内容,设置target属性为_blank以在新窗口中打开文件,设置download属性为要下载的文件名。接着模拟点击a标签来触发文件下载,并通过setTimeout函数在50毫秒后移除a标签。
最后,在指令的click事件中调用buildCSV函数来获取CSV文件内容,然后调用downloadFile函数来下载文件。
这样,就可以通过AngularJS从Web API中下载CSV文件了。
问题的原因是在使用上述代码下载csv文件时,下载的文件扩展名为.csv,但文件内部的内容不是文本,而是[object Object]。这是因为content是一个对象,而不是一个csv字符串。解决方法是将content转换为字符串,可以使用join('')将数组转换为字符串。
另外,还有一些附加的问题和解决方法。有用户提到在Firefox浏览器中无法正确设置文件名,这是因为设置文件名的代码应该是hiddenElement.download = 'myFile.csv',而不是hiddenElement = 'myFile.csv'。还有用户提到在Safari浏览器中无法正常工作,因为Safari不支持download属性,所以文件名也无法使用,它会下载一个名为'Unknown'的文件。
对于想要下载.xlsx文件而不是.csv文件的用户,可以尝试相同的方法创建文件,但是使用JS创建xlsx内容可能更加困难。
最后,还有用户提到使用这段代码下载大文件时遇到问题,但没有提供具体解决方法。
使用这段代码下载csv文件时,需要将content转换为字符串,并注意不同浏览器对文件名和文件类型的支持情况。对于其他问题,可能需要进一步调查和尝试其他解决方法。