【问题标题】:What is wrong with my download of a zip file from an ASP ApiController with AngularJS?我使用 AngularJS 从 ASP ApiController 下载 zip 文件有什么问题?
【发布时间】:2016-05-03 13:38:39
【问题描述】:

我正在尝试执行以下操作:

  1. 用户填写表格并将其以 .JSON 格式发送到服务器
  2. 使用该表单,服务器会生成一些 .CSV 文件并将它们全部放在一个 .ZIP 文件中。
  3. 服务器发送 .ZIP 文件,用户下载。

经过一番研究,我写了这段代码:

我的控制器:

[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 文件的方法。

当我调用我的控制器的提交方法时,我有一个 fileName.zip,它已下载到我的电脑上,但当我尝试打开它时,Windows 告诉我它不是一个有效的存档。

我做错了什么?我是 angularjs 和 ASP 的新手,欢迎任何帮助。

提前致谢。

【问题讨论】:

    标签: asp.net angularjs api http download


    【解决方案1】:

    您的代码存在几个问题:

    ZipArchive 完成工作后,流的位置将在末尾。所以你必须在发送之前将它重置为开头:

    zipStream.Position = 0;
    

    由于您已经在服务器上设置了文件的内容类型和文件名,因此只需在客户端解析它即可。

    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。您必须使用msSaveOrOpenBlobmsSaveBlob

    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()。感谢this thread,这可以通过添加这个小sn-p代码来解决:

    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);
    } 
    

    【讨论】:

    • 谢谢,只有一件事:如何在代码中初始化 blob 变量?
    • var blob = new Blob([data.data], {type: contentType});
    • 好的,谢谢,.ZIP 文件已完全返回但有一点:下载的文件名称很奇怪(例如:“6b046718-2d12-4d6e-9eef-90b4afa04628”)并且根本没有扩展。你知道我该如何解决这个问题吗?
    • 不要打电话给ContentDispositionHeaderValue,而是直接打电话给System.Net.Mime.ContentDisposition。像这样使用它:var cd = new System.Net.Mime.ContentDisposition { FileName = "fileName.zip", Inline = true }; result.Content.Headers.ContentDisposition = cd.ToString();
    • 或者,查看您的 regex 匹配项。 match 中的哪个位置包含您的文件名?
    猜你喜欢
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 2023-04-10
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    相关资源
    最近更新 更多