如何将 Excel (.xlsx) 文件导入并显示到 Blazor WASM 客户端(无需上传到服务器)

Wal*_*thi 6 c# npoi closedxml .net-5 blazor-webassembly

正如标题所说。网上有很多用于将文件上传到后端的示例,但我在验证客户端/离线后仅上传数据(无文件)。理论上,任何在 .Net5 上运行的东西都应该能够在 WASM 中以接近的性能运行。我正在尝试将这些繁重的操作卸载到客户的机器上。

我在 ClosedXML 方面取得了一些成功,但是当文件有几千行时,它会变得非常慢。在 Blazor 服务器端使用 ClosedXML 轻松加载 100,000 行。

笔记:

  • 使用 MudBlazor UI 组件
  • 我有一个来自文件的流,而不是 ClosedXML 的文件路径(就像我在控制台应用程序上一样),我认为这是 WASM 中的唯一方法,但我可能是错的。
  • 我在 NPOI 中运行了相同的代码,结果相似(WASM 慢,服务器端快)。
  • 我宁愿避免使用 EPPlus,除非它有神奇的修复方法。

页:

@page "/upload"
@inject HttpClient Http

<h1>Upload Data</h1>

<p>This component demonstrates uploading data from Excel.</p>

<InputFile id="fileInput" OnChange="UploadFiles" hidden single />

<MudButton HtmlTag="label"
           Variant="Variant.Filled"
           Color="Color.Primary"
           StartIcon="@Icons.Filled.CloudUpload"
           for="fileInput">
    Upload Files
</MudButton>

@if (dataTable == null)
{
    <p><em>Please upload Excel File</em></p>
}
else
{
    <MudTable Items="@dataTable.AsEnumerable().Take(500)" Hover="true" Breakpoint="Breakpoint.Sm" T="DataRow" RowsPerPage="100">
        <HeaderContent>
            @foreach (DataColumn col in dataTable.Columns)
            {
                <MudTh>@col.ColumnName</MudTh>
            }
        </HeaderContent>
        <RowTemplate>
            @foreach (var cell in context.ItemArray)
            {
                <MudTd>@cell.ToString()</MudTd>
            }
        </RowTemplate>
    </MudTable>
}

@code {
    //private IList<IBrowserFile> files = new List<IBrowserFile>();
    private DataTable dataTable;

    protected override async Task OnInitializedAsync()
    {
    }

    private async Task UploadFiles(InputFileChangeEventArgs e)
    {
        dataTable = await ExcelHelper.GetDataTableFromExcel(e.File);
    }
}
Run Code Online (Sandbox Code Playgroud)

功能:

public static async Task<DataTable> GetDataTableFromExcel(IBrowserFile file)
        {
            DataTable dtTable = new DataTable();

            using (MemoryStream memStream = new MemoryStream())
            {
                await file.OpenReadStream(file.Size).CopyToAsync(memStream);
                using (XLWorkbook workBook = new XLWorkbook(memStream, XLEventTracking.Disabled))
                {
                    //Read the first Sheet from Excel file.
                    IXLWorksheet workSheet = workBook.Worksheet(1);

                    //Loop through the Worksheet rows.
                    bool firstRow = true;
                    foreach (IXLRow row in workSheet.Rows())
                    {
                        //Use the first row to add columns to DataTable.
                        if (firstRow)
                        {
                            foreach (IXLCell cell in row.Cells())
                            {
                                dtTable.Columns.Add(cell.Value.ToString());
                            }
                            firstRow = false;
                        }
                        else
                        {
                            //Add rows to DataTable.
                            dtTable.Rows.Add();
                            int i = 0;

                            foreach (IXLCell cell in row.Cells(row.FirstCellUsed().Address.ColumnNumber, row.LastCellUsed().Address.ColumnNumber))
                            {
                                dtTable.Rows[dtTable.Rows.Count - 1][i] = cell.Value.ToString();
                                i++;
                            }
                        }
                    }
                }
            }
            return dtTable;
        }
Run Code Online (Sandbox Code Playgroud)

导致延迟的线路是:

using (XLWorkbook workBook = new XLWorkbook(memStream, XLEventTracking.Disabled))
Run Code Online (Sandbox Code Playgroud)

我需要帮助解决 xlsx 文件读取缓慢的问题,或者如果有更好的方法,则需要采用完全不同的方法!实现此目标的更好方法是不作弊/将文件上传到服务器:)