【问题标题】:an xlsm file is corrupted when dowloaded at client side在客户端下载时 xlsm 文件已损坏
【发布时间】:2016-09-11 11:25:43
【问题描述】:

请帮帮我... 我在服务器端(c#)有一个 xlsm 文件(带有宏的 excel),并想在客户端(javascript、angularjs)下载它。 所以..在服务器端控制器中我返回一个 HttpResponseMessage 并在客户端 - 下载它。

问题是打开下载的文件时,已经损坏了……

我做了一个简短的测试用例来演示这个问题。


服务器端(c# ApiController):

[HttpGet]
public HttpResponseMessage exportDPs()
{            
    var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
    var stream = new FileStream(@"D:\excel\data.xlsm", FileMode.Open);
    response.Content = new StreamContent(stream);
    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
    response.Content.Headers.ContentDisposition.FileName = "DPs.xlsm";
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    response.Content.Headers.ContentLength = stream.Length;
    response.StatusCode = System.Net.HttpStatusCode.OK;
    return response;
}

客户端(javascript、angularjs):

$scope.exportDPs = function () { 
    $http({
        method: GET,
        url: '../Api/DPs/exportDPs',
    }).success(function (data) { 
        var file = data;
        var encodedUri = encodeURI(file);
        var link = document.createElement("a");
        link.setAttribute("href", "data:application/vnd.ms-excel.sheet.macroEnabled.12;charset=utf-8,\uFEFF" + encodedUri);
        link.setAttribute("download", "DPs");
        link.click();                        
    })       
}

【问题讨论】:

  • 检查字节数以确保字节数没有改变。您的流可能正在使用损坏文件的默认 ASCII 编码。您需要使用不会更改文件的 UTF8 编码。我会使用以下内容: StreamReader stream = new StreamReader(@"D:\excel\data.xlsm", Encoding.UTF8);
  • 为什么要在文件内容前加上 BOM (\uFEFF)?这很可能是导致您的问题的原因。
  • 另外,为什么不把下载链接放到href属性中,然后调用.click()。尝试下载文件,然后从链接中将其作为数据 URI 提供,这会使您的问题变得不必要地复杂化。
  • 感谢您的回复和帮助!
  • Moshe Katz,当我提供文件的 URL 时,我收到错误消息 - 不允许加载本地资源。 jdweng,客户端的文件大小是OK的,也就是说服务器端没有损坏文件,只是下载的时候,文件变大了,文件损坏了……

标签: c# asp.net download data-uri xlsm


【解决方案1】:

问题可能是您为来自服务器的内容添加了 Unicode 字节顺序标记 (BOM) - \uFEFF 的前缀。 BOM 只对文本文件有用,但 XLSM 是二进制文件(更具体地说,它是 XML 文件的 ZIP 文件)。

但是,与其担心这个,最好的办法是简化您的 JavaScript,这样您就可以直接下载文件,而不是尝试在后台下载文件并从中生成数据 URI。

这应该做你想做的:

$scope.exportDPs = function () {
    var link = document.createElement("a");
    link.setAttribute("href", "../Api/DPs/exportDPs");
    link.setAttribute("download", "DPs");
    link.click();                        
}

【讨论】:

  • 再次感谢。现在还有其他事情让我感到不安——我的 URL 需要接收一个复杂的参数(对象数组)。如何在 URL 中执行此操作?
  • @mor 一个数组通常像这样在查询字符串中传递:?Values[]=1&Values[]=2&Values[]=3 对于这样的数组:Values = [1,2,3]。如果您需要比这更复杂的东西,您有两个简单的选择:1) 创建一个 JSON 字符串并将其传递到查询字符串中。 2) 创建一个form 元素,其中包含一堆input 元素而不是a 元素,并使用form.submit() 而不是link.click()。如果你需要更多帮助,你应该问另一个问题。
  • 谢谢,我会努力的。
猜你喜欢
  • 2020-01-13
  • 2020-11-10
  • 2015-03-16
  • 1970-01-01
  • 2019-01-21
  • 2014-08-09
  • 1970-01-01
  • 2015-07-14
  • 1970-01-01
相关资源
最近更新 更多