AngularJS如何下载Excel文件

在AngularJS中要下载一个Excel文件到底有多难呢?

最简单的方法

这当然是放一个 a 链接元素在页面搞定。

<a href="/path/file.xlsx" target="_blank">下载文件</a>

可如果我们涉及到一些身份验证,而且又是通过 Cookie,浏览器会很怪的一并发送到服务端,是不是一切都很好呢?

如果……

像上面说的如果我需要自定义请求头,例如:OWIN等身份验证的情况下,怎么办呢?

问题

也许我们可以非常简单的通过 ajax 发送一个 get 请求,并填写相应 headers,比如:

$http.get({
    url: '/path/file.xlsx',
    method: 'get',
    headers: {
        Authorization: 'Bearer pTVhzRZgA6yW-fp8c5vcxzBxr6vuIBYQrlo0ASIVxgkfN6'
    }
}).success(function (data) {
    // 怎么保存?
});

有一个办法就是我们可以通过 HTML5a 元素,指定一段 Base64 数据编码,我们可以生成一个 a 链接,然后点击下载。

这种方式在我的实验中,发现对于 Excel 支持不好,对于大一点的文件,下载回来都是无法打开。

Blob

Blob 存储的是二进制,实则就是一个 JavaScript 下的一个 File 对象,目前被大部分流行浏览器所支持。

我这里还找到一个 FileServer.js 是对 Blob 保存的具体实现。

以下是我结合 FileServer.js 写的一个AngularJS指令,好了,废话不多说:

App.directive('downFile', ['$http',function ($http) {
    return {
        restrict: 'A',
        scope: true,
        link: function (scope, element, attr) {
            var ele = $(element);
            ele.on('click', function (e) {
                ele.prop('disabled', true);
                e.preventDefault();
                $http({
                    url: attr.downFile,
                    method: 'get',
                    responseType: 'arraybuffer'
                }).success(function (data, status, headers) {
                    ele.prop('disabled', false);
                    var type;
                    switch (attr.downFileType) {
                        case 'xlsx':
                            type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
                            break;
                    }
                    if (!type) throw '无效类型';
                    saveAs(new Blob([data], { type: type }), decodeURI(headers()["x-filename"]));  // 中文乱码
                }).error(function (data, status) {
                    alert(data);
                    ele.prop('disabled', false);
                });
            });
        }
    };
}]);

相对于 View 的具体实现:

<button down-file="/order/export/{{item.id}}" down-file-type="xlsx" class="btn btn-green btn-sm">导出</button>

以下是 ASP.NET API 的具体实现:

HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
response.Content = new ByteArrayContent(pck.GetAsByteArray());
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.Add("x-filename", System.Web.HttpUtility.UrlEncode(item.title, System.Text.Encoding.UTF8) + ".xlsx"); // 中文乱码
return response;

中文文件名乱码问题

文件名为中文时获取到的 x-filename 会是乱码,所以需要进行编码,在示例中已经标识鸟。

写文章时比较仓促,所以示例中只对 Excel 进行转化,可以根据需求加入各种文件格式类型。

以上,希望帮助到各位。

4 Comments

  1. 请教一下~ 如果我想下载的时候客户端自行制定下载路径,并自动下载有没有什么办法呢?

    • asdf

      2016年4月13日 at 17:05

      下载路径取决于客户端应用程序吧,比如:Chrome有默认下载位置。这一方面无法程序干预;或许你自行封装一个浏览器客户端给用户使用应该可以做得到。

  2. 谢谢分享,我试了好像在safari下不支持,请教下有什么解决方法吗?

    • asdf

      2016年7月5日 at 12:25

      这个办法的核心关键是浏览器必须支持Blob,你可以去核实safari这个版本是否支持它。

发表评论

Your email address will not be published.

*

© 2017 卡片机色彩 沪ICP备13032872号-3

Theme by cipchk

to top