从 ASP.NET Core MVC 应用程序导出的 Excel 已损坏

问题描述 投票:0回答:1

我需要专家意见来解决有线问题。我尝试了很多替代方案,但都失败了。

上下文:我想编写一个实用程序作为 ASP.NET Core MVC Web 应用程序,它将使用各种工作表将一些数据从数据库导出到 Excel 工作簿。

问题陈述:应用程序正在导出Excel工作簿。但是一旦用户单击下载的文件即可打开。错误消息显示文件已损坏。尽管该文件包含一些数据。

客户端代码:

 $(document).on('click', '#btnDataExport', function () {
        var zId = $("#deZone").val();
        var fId = $("#deFactory").val();
        var mId = $('#deMarket').val();
        var selectedCheckboxes = $('input.chk:checked');
        var selectedIds = [];
        selectedCheckboxes.each(function () {
            selectedIds.push($(this).attr('id'));
        });
        var zoneIdsStr = zId.join(',');
        var marketIdsStr = mId.join(',');
        var factoryIdsStr = fId.join(',');
        $.ajax({

            cache: false,
            type: 'POST',
            url: '/DataExport/DataExport',
            data: {
                entities: selectedIds,
                zoneIds: zoneIdsStr,
                marketIds: marketIdsStr,
                factoryIds: factoryIdsStr
               
            },
           
            success: function (data) {
                
                var blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
                
                var link = document.createElement('a');
                link.href = window.URL.createObjectURL(blob);
                link.download = 'Export.xlsx';
                link.click();
                
            },
            error: function () {
                alert("Error while loading the page");
            }    
        });
    });

服务器端代码:

[HttpPost]
public async Task<IActionResult> DataExport(List<string> entities, List<int> zoneIds, List<int>marketIds,List<int> factoryIds)
{
    // byte[] fileContents;
    using (var package = new ExcelPackage())
    {
        foreach (var entity in entities)
        {
            if (string.Compare(entity, "YearlyZoneKPIs", false) == 0)
            {
                var yearlyZoneKPIs = _dataexportservice.GetYearlyZoneKpis(zoneIds, marketIds);
                ExcelWorksheet worksheetyearlyZoneKPIs = package.Workbook.Worksheets.Add("YearlyZoneKPIs");
                DataExportExcelFactory.CreateExcelForYearlyZoneKPIs(ref worksheetyearlyZoneKPIs, yearlyZoneKPIs);
             }
         }
    }

    using (MemoryStream mstream = new MemoryStream())
    {
        package.SaveAs(mstream);
        return File(mstream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "ExportedData.xlsx");
    }
}    

这里

DataExportExcelFactory.CreateExcelForYearlyZoneKPIs
是一个静态方法,用于通过引用使用第二个参数中传递的数据(此处为yearlyZoneKPIs)填充Excel。

c# excel asp.net-core-mvc
1个回答
0
投票

在您的代码中,放置在

using
周围的
MemoryStream
块将在
File()
结果中使用流之前处理该流,因为它是在
using
块的范围之外返回的。确保内存流保持打开且可用,直到文件完全写入响应。

这里的代码将在文件写入响应后处理 MemoryStream 的处置,因此您不需要手动处置它。

[HttpPost]
public async Task<IActionResult> DataExport(List<string> entities, List<int> zoneIds, List<int> marketIds, List<int> factoryIds)
{
    using (var package = new ExcelPackage())
    {
        // ... (adding worksheets code)

        var memoryStream = new MemoryStream();
        package.SaveAs(memoryStream);
        memoryStream.Position = 0; 

        return File(memoryStream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "ExportedData.xlsx", true);
    }
}

除此之外,如果您使用

$.ajax
获取数据,jQuery 可能无法正确处理二进制数据,因为它事先不知道响应的数据类型。您可以使用 Fetch API 尝试以下方法,其中
responseType
blob
,或者如果坚持使用 jQuery
,则设置正确的 
xhrFields

fetch('/DataExport/DataExport', {
    method: 'POST',
    body: JSON.stringify({
        entities: selectedIds,
        zoneIds: zoneIdsStr,
        marketIds: marketIdsStr,
        factoryIds: factoryIdsStr
    }),
    headers: {
        'Content-Type': 'application/json'
    }
}).then(response => response.blob())
  .then(blob => {
    var url = window.URL.createObjectURL(blob);
    var a = document.createElement('a');
    a.href = url;
    a.download = 'Export.xlsx';
    document.body.appendChild(a);
    a.click();    
    a.remove(); 
}).catch(error => console.error('Error:', error));
© www.soinside.com 2019 - 2024. All rights reserved.