Update
I set this aside for a bit but I'm back on it now. I haven't been able to find anything that helps. Does anyone know a way I can debug what is happening inside the CopyToAsync function or a way I can see where the bottle neck is. Either from the client machine end or the web server end. I've been a developer for some time but am new to web development so I'm not familiar with the browser dev tools or anything that could help me locate this issue. Any suggestions would be appreciated as I'm completely stuck at this point.
Problem
I'm experiencing what seems to be very slow upload speeds. About 22 or 23 seconds to upload an 8MB file. Within the LAN the webserver is on it takes 2 or 3 seconds. Through some logging I've narrowed it down that all the time is spent in my call to Stream.CopyToAsync(). At the bottom I put the two log outputs to show the upload difference between local and remote. All the other code before and after the CopyToAsync runs fast. I've included the code for the blazor component I made below.
Research
I've checked the following cases plus lots of other reading but haven't seemed to find anything yet that has helped.
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
What I've Tried
As you can see in the code I tried adding adding some FileOptions to the FileStream but that had no effect on the speed. I've also tried ConfigureAwait but that didn't improve speed and also crashed it after the first file. I think that is because this is in the UI thread. At least that's what I assumed from my research. I'm not new to programming but I am new to web programming and especially Blazor.
Other Points
Both server and remote client are in locations with high speed internet (within the same city) and the web server does not have a heavy load on it.
Questions
Is 23 seconds for 8MB normal for the way the code is designed or do you think this is excessive too?
Is my code the correct approach? It does function pretty solid except for the speed.
Any suggestions on things to try or to research to fix this?
Code
@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;
}
}
}
Local Log
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
Remote Log
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