【发布时间】:2021-01-05 17:52:50
【问题描述】:
我有一个 blazor 服务器端应用程序,其中一个页面使用以下代码推送文件下载:
nav.NavigateTo("/download/" + fileName, true);
通过将页面重定向到文件并弹出下载对话框,效果很好。但是,在此操作之后,应用程序会死掉。
错误:电路因错误而关闭。
我必须刷新页面以重新建立连接才能继续。
我应该做一些不同的事情来允许用户下载文件吗?
【问题讨论】:
我有一个 blazor 服务器端应用程序,其中一个页面使用以下代码推送文件下载:
nav.NavigateTo("/download/" + fileName, true);
通过将页面重定向到文件并弹出下载对话框,效果很好。但是,在此操作之后,应用程序会死掉。
错误:电路因错误而关闭。
我必须刷新页面以重新建立连接才能继续。
我应该做一些不同的事情来允许用户下载文件吗?
【问题讨论】:
对于使用 .NET 5 RC2 的任何人
如果您使用的是 .NET 5 RC2 或更高版本,则此解决方案将不适用于您,并且上述问题中显示的代码应符合 this issue 的要求。如果您仍然遇到问题,则可能是您遇到了其他问题。
适用于使用 .NET 5 RC2 之前版本的任何人
要记住的是,使用 Blazor 时,所有通信都是通过 websocket 进行的。这可能会在处理文件下载时出现问题,因为任何远离套接字的导航(例如导航到静态文件)都会中断连接。
处理这个问题的一个简单方法是使用像BlazorDownloadFile 这样的包。
为了使用它,只需使用以下命令安装 nuget:
Install-Package BlazorDownloadFile -Version 2.1.2
接下来在 Startup.cs 文件的 ConfigureServices 方法中添加以下行:
services.AddBlazorDownloadFile();
现在您可以注入 IBlazorDownloadFileService 并使用它来下载文件。我在下面包含了一个这样的用法示例,它只是从与正在执行的程序集相同的目录下载文本文件。
@page "/"
@using BlazorDownloadFile
@using System.IO
@using System.Reflection
@using System.Threading
<h1>Hello, world!</h1>
Welcome to your new app.
@Message
<br/>
<SurveyPrompt Title="How is Blazor working for you?"/>
<button @onclick="OnClicked">Download File</button>
@code{
[Inject] IBlazorDownloadFileService BlazorDownloadFileService { get; set; }
public string Message = String.Empty;
public async Task OnClicked()
{
var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "TestDownloadFile.txt");
var bytes = File.ReadAllBytes(path);
var task = await BlazorDownloadFileService.DownloadFile("testdownload.txt", bytes.ToList(),CancellationToken.None,"application/octet-stream");
if (task.Succeeded)
{
Message = "Successful download!";
}
else
{
Message = task.ErrorMessage;
}
}
}
如您所见,这样您就可以轻松地让用户下载文件而不会冒中断 websocket 连接的风险,并且您可以获得有关是否存在问题的反馈,以便实施适当的错误处理。
Github Project 中提到了一些注意事项,您可能需要注意:
关于我在这个库中所做的一些性能测试是 也就是说,base64 字符串和 byte[] 的执行速度总是比 Stream 快。
由于从 c# Stream 到 a JavaScript 对象在这项任务中的开销要大一些。
当它的 base64 是最简单的数据类型传输和工作 用它。
byte[] 在传输到 JavaScript,由于某种原因,它在编码时无法正常工作 导致它的base64表示在进行时变成了别的东西 在第二个分区之后被编码为 base64 字符串。 (如果 任何人都知道如何修复或解决此问题,请提出拉取请求)
基于 las 语句,字节列表从 c# 传递到 JavaScript 作为整数数组,字节表示为 on JavaScript,这就是我发送 IList 而不是 byte[] 在 JavaScript 内部。
二进制表示似乎表现得很好,因为我们刚刚 需要调用 Uint8Array 并完全推送二进制表示 进入数组,然后将其传递给 JavaScript 原生 Blob 对象。
【讨论】:
您展示的代码应该可以工作——并且对我有用。这个问题似乎是一个困扰很多人的已知(新)问题。您可以在此处找到有关该问题的更多信息:https://github.com/dotnet/aspnetcore/issues/25646
他们说他们正在努力解决这个问题,但目前还没有预计到达时间。很抱歉,我没有一个像样的解决方法可以分享——我自己还在探索。
【讨论】: