【发布时间】:2021-07-07 22:12:34
【问题描述】:
更新
我暂时搁置了这一点,但我现在又回来了。我找不到任何有帮助的东西。有谁知道我可以调试 CopyToAsync 函数内部发生的事情的方法,或者我可以看到瓶颈在哪里的方法。从客户端计算机端或 Web 服务器端。我做开发人员已经有一段时间了,但对 Web 开发很陌生,所以我不熟悉浏览器开发工具或任何可以帮助我找到这个问题的东西。任何建议都将不胜感激,因为我完全被困在这一点上。
问题
我的上传速度似乎很慢。上传一个 8MB 的文件大约需要 22 或 23 秒。在 LAN 内,网络服务器启动需要 2 或 3 秒。通过一些日志记录,我缩小了所有时间都花在了对 Stream.CopyToAsync() 的调用上。在底部,我放置了两个日志输出以显示本地和远程之间的上传差异。 CopyToAsync 之前和之后的所有其他代码都运行得很快。我已经包含了我在下面制作的 blazor 组件的代码。
研究
我已经检查了以下案例以及许多其他阅读材料,但似乎还没有发现任何有用的东西。
Should I call ConfigureAwait(false) on every awaited operation
Increase Speed for Streaming Large(1-10 gb) files .Net Core
Extremely Slow file upload to a Blazor Server app deployed as Azure Web App
我的尝试
正如您在代码中看到的那样,我尝试向 FileStream 添加一些 FileOptions,但这对速度没有影响。我也尝试过 ConfigureAwait 但这并没有提高速度并且在第一个文件之后也崩溃了。我认为这是因为这是在 UI 线程中。至少这是我从研究中假设的。我对编程并不陌生,但我对 Web 编程尤其是 Blazor 很陌生。
其他要点
服务器和远程客户端都位于具有高速互联网的位置(在同一城市内),并且网络服务器的负载不重。
问题
8MB 的 23 秒对于代码的设计方式是正常的还是你认为这也太夸张了?
我的代码是正确的方法吗?除了速度之外,它的功能确实非常可靠。
有什么建议可以尝试或研究来解决这个问题吗?
代码
@using System.IO
@inject SessionService session
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment env
@inject IJSRuntime JSRuntime
@if (showMessage)
{
<div style="font-size: 20px;" class="alert-danger border-danger">
<p>@userMessage</p>
</div>
}
<button class="btn btn-primary m-2" onclick="document.getElementById('filepicker').click()" disabled="@disabled">@buttonText</button>
<InputFile id="filepicker" OnChange="@OnInputFileChange" hidden multiple="@multipleFiles" />
@code
{
[Parameter] public EventCallback<FileModel> OnFileAdd { get; set; }
[Parameter] public EventCallback<int> OnUploadStart { get; set; }
[Parameter] public EventCallback<bool> OnUploadEnd { get; set; }
[Parameter] public string buttonText { get; set; } = "Upload";
[Parameter] public bool multipleFiles { get; set; } = false;
[Parameter] public int callBackRefID { get; set; } = 0;
private IReadOnlyList<IBrowserFile> selectedFiles;
private bool showMessage = false;
private bool disabled = false;
private MarkupString userMessage;
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
if (e.FileCount > 0)
{
disabled = true;
await JSRuntime.InvokeAsync<string>("console.log", "Starting " + e.FileCount + " files - " + DateTime.Now.ToString());
await OnUploadStart.InvokeAsync(e.FileCount);
selectedFiles = e.GetMultipleFiles(e.FileCount);
foreach (var file in selectedFiles)
{
await JSRuntime.InvokeAsync<string>("console.log", "Starting " + file.Name + " - " + DateTime.Now.ToString());
Stream stream = file.OpenReadStream((long)2147483648);
var path = $"{env.WebRootPath}\\Uploads\\{file.Name}";
//FileOptions had no effect on performance
FileStream fs = File.Create(path, 1048576, FileOptions.Asynchronous | FileOptions.SequentialScan);
//FileStream fs = File.Create(path, 1048576);
await JSRuntime.InvokeAsync<string>("console.log", "Before stream.CopyToAsync - " + DateTime.Now.ToString());
await stream.CopyToAsync(fs, 1048576);
//ConfigureAwait causes crash after first file is done.
//await stream.CopyToAsync(fs, 1048576).ConfigureAwait(false);
await JSRuntime.InvokeAsync<string>("console.log", "After stream.CopyToAsync - " + DateTime.Now.ToString());
stream.Close();
fs.Close();
FileModel upFile = new();
upFile.S_ID = session.CurrentUser.ID;
upFile.Name = file.Name;
upFile.DisplayName = "";
upFile.Descr = "";
upFile.ContentType = file.ContentType;
if (upFile.GetFileData(path, file.ContentType) == false)
{
userMessage = new(upFile.ErrMsg);
showMessage = true;
await OnUploadEnd.InvokeAsync(false);
return;
}
await OnFileAdd.InvokeAsync(upFile);
await JSRuntime.InvokeAsync<string>("console.log", "Finished " + file.Name + " - " + DateTime.Now.ToString());
}
await OnUploadEnd.InvokeAsync(true);
await JSRuntime.InvokeAsync<string>("console.log", "Finished - " + DateTime.Now.ToString());
disabled = false;
}
}
}
本地日志
blazor.server.js:1 Starting 3 files - 2021-04-12 2:01:33 PM
blazor.server.js:1 Starting IMG_7830.JPG - 2021-04-12 2:01:33 PM
blazor.server.js:1 Before stream.CopyToAsync - 2021-04-12 2:01:33 PM
blazor.server.js:1 After stream.CopyToAsync - 2021-04-12 2:01:36 PM
blazor.server.js:1 Finished IMG_7830.JPG - 2021-04-12 2:01:37 PM
blazor.server.js:1 Starting IMG_7831.JPG - 2021-04-12 2:01:37 PM
blazor.server.js:1 Before stream.CopyToAsync - 2021-04-12 2:01:37 PM
blazor.server.js:1 After stream.CopyToAsync - 2021-04-12 2:01:40 PM
blazor.server.js:1 Finished IMG_7831.JPG - 2021-04-12 2:01:41 PM
blazor.server.js:1 Starting IMG_7832.JPG - 2021-04-12 2:01:41 PM
blazor.server.js:1 Before stream.CopyToAsync - 2021-04-12 2:01:41 PM
blazor.server.js:1 After stream.CopyToAsync - 2021-04-12 2:01:43 PM
blazor.server.js:1 Finished IMG_7832.JPG - 2021-04-12 2:01:44 PM
blazor.server.js:1 Finished - 2021-04-12 2:01:44 PM
远程日志
blazor.server.js:1 Starting 3 files - 2021-04-12 12:01:44 PM
blazor.server.js:1 Starting IMG_7830.JPG - 2021-04-12 12:01:45 PM
blazor.server.js:1 Before stream.CopyToAsync - 2021-04-12 12:01:45 PM
blazor.server.js:1 After stream.CopyToAsync - 2021-04-12 12:02:07 PM
blazor.server.js:1 Finished IMG_7830.JPG - 2021-04-12 12:02:08 PM
blazor.server.js:1 Starting IMG_7831.JPG - 2021-04-12 12:02:08 PM
blazor.server.js:1 Before stream.CopyToAsync - 2021-04-12 12:02:08 PM
blazor.server.js:1 After stream.CopyToAsync - 2021-04-12 12:02:30 PM
blazor.server.js:1 Finished IMG_7831.JPG - 2021-04-12 12:02:31 PM
blazor.server.js:1 Starting IMG_7832.JPG - 2021-04-12 12:02:31 PM
blazor.server.js:1 Before stream.CopyToAsync - 2021-04-12 12:02:31 PM
blazor.server.js:1 After stream.CopyToAsync - 2021-04-12 12:02:53 PM
blazor.server.js:1 Finished IMG_7832.JPG - 2021-04-12 12:02:54 PM
blazor.server.js:1 Finished - 2021-04-12 12:02:54 PM
【问题讨论】:
标签: c# file stream blazor blazor-server-side