从 WebAPI ASPNetCore 返回 Excel 文件

Posted

技术标签:

【中文标题】从 WebAPI ASPNetCore 返回 Excel 文件【英文标题】:Return Excel File from WebAPI ASPNetCore 【发布时间】:2017-06-04 10:03:24 【问题描述】:

我正在尝试创建 WebAPI,它将使用 ClosedXML 库返回 Excel 文件。

如果我返回 FileStreamResult,一切正常。但是,如果我将其更改为 HttpResponseMessage,正如这里所讨论的 Web API Return A File,我将无法下载文件或查看内容并获取 JSON 字符串。

我想知道如何从这个 HttpResponseMessage 中提取文件内容。

我在浏览器或 PostMan 工具中进行了测试,得到的只是 JSON 字符串:


      "version": 
        "major": 1,
        "minor": 1,
        "build": -1,
        "revision": -1,
        "majorRevision": -1,
        "minorRevision": -1
      ,
      "content": 
        "headers": [
          
            "key": "Content-Disposition",
            "value": [
              "attachment; filename=ERSheet.xlsx"
            ]
          ,
          
            "key": "Content-Type",
            "value": [
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            ]
          
        ]
      ,
      "statusCode": 200,
      "reasonPhrase": "OK",
      "headers": [],
      "requestMessage": null,
      "isSuccessStatusCode": true
    

我的代码如下:

[HttpGet("ERSheet2")]
        public HttpResponseMessage ER_GenerateWBLWorksheet2()
        
            MemoryStream stream = new MemoryStream();
            var workbook = new XLWorkbook();

            var SheetNames = new List<string>()  "15-16", "16-17", "17-18", "18-19", "19-20" ;

            foreach (var sheetname in SheetNames)
            
                var worksheet = workbook.Worksheets.Add(sheetname);

                worksheet.Cell("A1").Value = sheetname;
            

            workbook.SaveAs(stream);
            stream.Seek(0, SeekOrigin.Begin);

            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
            result.Content = new ByteArrayContent(stream.ToArray());
            result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            result.Content.Headers.ContentDisposition.FileName = "ERSheet.xlsx";
            return result;
        

更新

这与这个问题Download file with ClosedXML 不同,因为我提到我已经通过使用'FileStreamResult' 使它工作。我之所以问这个问题是因为这个评论“最好返回带有 StreamContent 的 HttpResponseMessage ”。在此线程Web API Return A File 中制作。因此,尝试在 .Net Core 中使用 HttpResponseMessage 并且不知道它不再支持 Darin 的答案。

【问题讨论】:

此 ResponseMessage 没有任何内容。我的意思是Excel文件的内容。还是我不对? 对不起,我很困惑。我的 ResponseMessage 不包含任何内容或 HttpResponseMessage 不能用于保存任何内容? Download file with ClosedXML的可能重复 首先,您的 JSON 字符串没有 Excel 文件的任何内容 【参考方案1】:

在 .NET Core 上运行的 ASP.NET Web API 不再支持 HttpResponseMessage。因此,基本上它会尝试序列化您要返回到 JSON 的该对象的实例(就好像它是您的简单视图模型一样)。您可以使用一些compatibility shim hacks,但总的来说,我建议您使用更惯用的方法 - 从您的操作中返回一个IActionResult 实例:

[HttpGet("ERSheet2")]
public IActionResult ER_GenerateWBLWorksheet2()

    using (MemoryStream stream = new MemoryStream())
    
        var workbook = new XLWorkbook();

        var SheetNames = new List<string>()  "15-16", "16-17", "17-18", "18-19", "19-20" ;

        foreach (var sheetname in SheetNames)
        
            var worksheet = workbook.Worksheets.Add(sheetname);

            worksheet.Cell("A1").Value = sheetname;
        

        workbook.SaveAs(stream);
        stream.Seek(0, SeekOrigin.Begin);

        return this.File(
            fileContents: stream.ToArray(), 
            contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 

            // By setting a file download name the framework will
            // automatically add the attachment Content-Disposition header
            fileDownloadName: "ERSheet.xlsx"
        );
    

【讨论】:

对,应该是主要原因。我试图在另一个答案中将它返回到这一行的 HttpResponse 中。 “最好返回带有 StreamContent 的 HttpResponseMessage。”谢谢。 是的,但这个答案是关于在完整 .NET 框架上运行的 ASP.NET Web API,而不是针对 .NET Core。 您如何看出该问题与 .Net 核心还是标准 .Net 相关?我在页面上的任何地方都找不到这些主题标签。【参考方案2】:

我相信你应该使用:

response.Content = new ByteArrayContent(stream.GetBuffer());

但是,我无法让它为 Angular2 工作。它确实适用于 Angular1。

【讨论】:

不清楚这个答案是如何相关的。这个问题没有提到使用 Angular。但也许你看到了我没有看到的东西,并且可以帮助提问者澄清问题?

以上是关于从 WebAPI ASPNetCore 返回 Excel 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用Swashbuckle.AspNetCore生成.NetCore WEBAPI的接口文档

将 httpHandler 附加到 httpclientFactory webapi aspnetcore 2.1

我可以在 AspNetCore WebAPI 中将 CancellationToken 作为参数传递吗

异常处理中间件不处理异常 - 调用 Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware (ASP.NET Core WebAPI)

手把手教你AspNetCore WebApi:Nginx(负载均衡)

直接从令牌获取 JWT 声明,ASP Net Core 2.1