我从带有 AngularJS 的 ASP ApiController 下载 zip 文件有什么问题? [英] What is wrong with my download of a zip file from an ASP ApiController with AngularJS?
问题描述
我正在尝试执行以下操作:
I'm trying to do the following:
- 用户填写表单并将其以 .JSON 格式发送到服务器
- 使用该表单,服务器生成一些 .CSV 文件并将它们全部放在一个 .ZIP 文件中.
- 服务器发送 .ZIP 文件,用户下载它.
经过一番研究,我写了这段代码:
After some research I have wrote this code:
我的控制器:
[HttpPost]
[Route("routeToMyAPI")]
public HttpResponseMessage Process(Form form)
{
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(<streamToMyGeneratedZipFile>)
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "fileName.zip"
};
return result;
}
我的服务:
angular.module('app')
.factory('MyService', function ($http) {
return {
Process: function (form) {
var req = $http.post('rest/example/process', form);
return req;
}
};
});
我的控制器:
this.submit = function () {
var Form = {};
var formPost = MyService.Process(Form);
formPost.then(function (data) {
var a = document.createElement('a');
var blob = new Blob([data], { 'type': "application/octet-stream" });
a.href = URL.createObjectURL(blob);
a.download = "fileName.zip";
a.click();
}, function (error) {
alert('An error occured !');
});
};
我有第 1 部分 &2 工作正常,但我没有找到调用我的 ASP API 来下载 .ZIP 文件的方法.
I have parts 1 & 2 working, but I don't have find the way to call my ASP API to download the .ZIP file.
当我调用我的控制器的提交方法时,我有一个 fileName.zip 下载到我的电脑上,但是当我尝试打开它时,Windows 告诉我它不是一个有效的存档.
When I call the submit method of my Controller, I have a fileName.zip who is downloaded on my PC but when I try to open it Windows says to me that it's not a valid archive.
我做错了什么?我是 angularjs 和 ASP 的新手,因此欢迎提供任何帮助.
What did I do wrong ? I'm a rookie in angularjs and ASP so any help will be welcomed.
提前致谢.
推荐答案
您的代码的几个问题:
ZipArchive
完成工作后,流的位置将位于末尾.所以你必须在发送之前像这样将它重置为开头:
After ZipArchive
does its work, the position of the stream will be at the end. So you must reset it to the beginning like this before sending it:
zipStream.Position = 0;
由于您已经在服务器上设置了文件的内容类型和文件名,因此只需在客户端解析即可.
Since you're setting the content type and file name of the file on the server already, just parse it on the client side.
var headers = data.headers(); //$http resolves to data, status, headers, config
var regex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var match = regex.exec(headers["content-disposition"]);
var fileName = match[1] || "myZipFile.zip";
fileName = fileName.replace(/\"/g, ""); //replace trailing and leading slashes
var contentType = headers["content-type"] || "application/octet-stream";
IE 不允许您直接打开 blob.您必须使用 msSaveOrOpenBlob
或 msSaveBlob
.
IE will not allow you to open blobs directly. You must use msSaveOrOpenBlob
or msSaveBlob
.
var blob = new Blob([data.data], { type: contentType });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
var a = document.createElement('a');
var objectUrl = URL.createObjectURL(blob);
a.href = URL.createObjectURL(blob);
a.download = match[1];
a.click();
}
最后一件事:之前的代码在 firefox 上不起作用,因为 firefox 不支持 clic()
.感谢 这个线程 这可以通过添加这个小片段来解决代码:
One last thing: the previous code won't work on firefox because firefox doesn't support clic()
. Thanks to this thread this can be solved by adding this little snippet of code:
HTMLElement.prototype.click = function() {
var evt = this.ownerDocument.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
this.dispatchEvent(evt);
}
这篇关于我从带有 AngularJS 的 ASP ApiController 下载 zip 文件有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!