使用 closedxml 从 web api 下载 excel 文件

Posted

技术标签:

【中文标题】使用 closedxml 从 web api 下载 excel 文件【英文标题】:Downloading excel file from web api using closedxml 【发布时间】:2018-02-01 23:21:35 【问题描述】:

我无法通过 Web API 下载由 closedxml 创建的 excel 文件。 如果我将文件保存在服务器上看起来不错,但是一旦我将其放入流中并将其返回到 Web api,那么浏览器中只会收到一个损坏的文件。

正如几篇文章所建议的那样,我使用 httpResponseMessage,但在浏览器中,标题中的文件名永远不会到达。

我们正在使用:

"Microsoft.AspNet.WebApi" 版本="5.2.3" targetFramework="net461

"ClosedXML" 版本="0.88.0" targetFramework="net461"

WebAPI 代码:

 var wb = new XLWorkbook();
            var ws = wb.Worksheets.Add("Parcel List");


            MemoryStream fs = new MemoryStream();
            wb.SaveAs(fs);
            fs.Position = 0;


            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
            result.Content = new ByteArrayContent(fs.GetBuffer());
            result.Content.Headers.ContentLength = fs.Length;
            result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            
                FileName = "List" + "_" + DateTime.Now.ToShortDateString() + ".xlsx"
            ;
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            return result;

这里是javascript代码:

  context.$http.post(config.get_API_URL() + 'api_call',  excel_list,
        responseType: 'application/octet-stream')
  .then(
    success_function,
    error_function)

成功函数:

function(response) 

                  var headers = response.headers;
                 var blob = new Blob([response.body],
                                     type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                                   );

                 window.open(window.URL.createObjectURL(blob));

                

【问题讨论】:

如果保存文件,重命名为.zip,可以打开吗?我试图弄清楚内部是否损坏或包装是否在传输过程中损坏。 我将工作簿保存在服务器上并将其重命名为 .zip,可以打开它并查看结构。所以似乎是传输破坏了它 如果您可以打开 .zip 文件,则不是传输损坏了它。当您将文件保存在服务器上时,您可以检查内容长度与文件的确切长度吗? 也看看***.com/a/24129082/179494 - 似乎不支持通过 AJAX 下载文件。它可能适用于您。 【参考方案1】:

我现在可以使用此代码成功下载工作簿:

using ClosedXML.Excel;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;

namespace ClosedXML.Extensions.WebApi.Controllers

    public class ValuesController : ApiController
    
        public IHttpActionResult Get(int id)
        
            return new TestFileActionResult(id);
        
    

    public class TestFileActionResult : IHttpActionResult
    
        public TestFileActionResult(int fileId)
        
            this.FileId = fileId;
        

        public int FileId  get; private set; 

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        
            HttpResponseMessage response = null;

            var ms = new MemoryStream();
            using (var wb = new XLWorkbook())
            
                var ws = wb.AddWorksheet("Sheet1");
                ws.FirstCell().Value = this.FileId;

                wb.SaveAs(ms);

                ms.Seek(0, SeekOrigin.Begin);

                response = new HttpResponseMessage(HttpStatusCode.OK);
                response.Content = new StreamContent(ms);
                response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                response.Content.Headers.ContentDisposition.FileName = "test.xlsx";
                response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

                response.Content.Headers.ContentLength = ms.Length;
                ms.Seek(0, SeekOrigin.Begin);
            

            return Task.FromResult(response);
        
    

【讨论】:

谢谢,但是 javascript 部分如何查找 web api 调用并自行下载?感觉有问题。 我不是 JavaScript 专家。但是请看***.com/a/24129082/179494 中的问答。看起来对您尝试做的事情有不同的支持。我的建议是尝试直接使用&lt;a&gt; 标签,而不是通过 AJAX 调用下载文件【参考方案2】:

问题似乎是 web api 调用的响应类型必须是 responseType: 'arraybuffer' 而不是 responseType: 'application/octet-stream'

context.$http.post('api-url', excel_list, responseType: 'arraybuffer') .then( success_function, error_function)

感谢您的快速帮助

【讨论】:

【参考方案3】:

看看https://www.nuget.org/packages/ClosedXML.Extensions.Mvc/的Mvc扩展包

PS:有人告诉我,我每次都必须否认这一点。我是 ClosedXML 和 ClosedXML.Extensions.Mvc 的维护者。

【讨论】:

不幸的是,这也不起作用。我们使用的是 Web API 而不是 MVC。我在 javascript 中收到了相同的结果,还有来自该扩展名的“FileStreamResult”。 好的。我会监控这个问题,如果有解决方案,我会将其添加到该扩展程序中。

以上是关于使用 closedxml 从 web api 下载 excel 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery Ajax 调用从 ASP.NET Web Api 下载 CSV 文件

显示/交互/可见 ClosedXML Excel.XLWorkbook 不保存

在 ASP.NET MVC 5 控制器中使用 POST 从 dotnet Core Web API 下载文件

从 Web API 核心下载文件 - Angular 7

excel的当前格式在 Closedxml SaveAs 方法中发生变化

EPPlus 和 ClosedXML 库在处理 OpenXML 方面有啥区别? [关闭]