【发布时间】:2021-02-22 04:39:24
【问题描述】:
我想实现一个大文件上传进度演示,但是下面的代码不能正常工作。 如果删除 ProgressableStreamContent 类中的代码“await Task.Delay(1)”,并且 id“mybar”元素不刷新 UI。 如果添加“await Task.Delay(1)”,则工作正常。可以刷新UI,显示进度。为什么? 有没有人遇到过这个问题?你能帮我解决这个问题吗?谢谢。
<p>
<InputFile OnChange="@OnInputFileChange" />
</p>
<div>
<p>File Size:@totalSize @progressPercent % </p>
@{
var progressWidthStyle = progressPercent + "%";
}
<div class="progress">
<div id="mybar" class="progress-bar" role="progressbar" style="width:@progressWidthStyle" area-valuenow="@progressPercent" aria-minvalue="0" aria-maxvalue="100"></div>
</div>
</div>
private CancellationTokenSource cancelation;
public long totalSize = 0;
public int progressPercent = 0;
private string _fileName = "";
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
IBrowserFile imageFile = e.File;
totalSize = imageFile.Size;
var buffer = new byte[totalSize];
await imageFile.OpenReadStream(512000*1000).ReadAsync(buffer);
var content = new MultipartFormDataContent { { new ByteArrayContent(buffer), "\"upload\"", e.File.Name } };
var progressContent = new ProgressableStreamContent(content, 10240,
(sent, total) =>
{
progressPercent = (int)(sent * 100 / total);
Console.WriteLine("Uploading {0}%", progressPercent);
StateHasChanged();
});
var repsone = await client.PostAsync("http://localhost:5000/Home/Upload", progressContent);
var taskStr = await repsone.Content.ReadAsStringAsync();
Console.WriteLine("taskStr=" + taskStr);
}
public class ProgressableStreamContent : HttpContent
{
/// <summary>
/// Lets keep buffer of 20kb
/// </summary>
private HttpContent content;
private int bufferSize;
//private bool contentConsumed;
private Action<long, long> progress;
public ProgressableStreamContent(HttpContent content, int bufferSize, Action<long, long> progress)
{
if (content == null)
{
throw new ArgumentNullException("content");
}
if (bufferSize <= 0)
{
throw new ArgumentOutOfRangeException("bufferSize");
}
this.content = content;
this.bufferSize = bufferSize;
this.progress = progress;
foreach (var h in content.Headers)
{
this.Headers.Add(h.Key, h.Value);
}
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
var buffer = new Byte[this.bufferSize];
long size;
TryComputeLength(out size);
var uploaded = 0;
using (var sinput = await content.ReadAsStreamAsync())
{
while (true)
{
var length = sinput.Read(buffer, 0, buffer.Length);
if (length <= 0) break;
//downloader.Uploaded = uploaded += length;
uploaded += length;
progress?.Invoke(uploaded, size);
await Task.Delay(1);
//System.Diagnostics.Debug.WriteLine($"Bytes sent {uploaded} of {size}");
await stream.WriteAsync(buffer, 0, length);
}
}
stream.Flush();
}
protected override bool TryComputeLength(out long length)
{
length = content.Headers.ContentLength.GetValueOrDefault();
return true;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
content.Dispose();
}
base.Dispose(disposing);
}
}
【问题讨论】:
-
WebAssembly 在单线程上运行,要更改进度,我们必须使用
Task.Delay(1)再次更改刷新。检查以下线程:Blazor WebAssembly: How to get UI to update during long running, non-async process 和 Blazor - Display wait or spinner on API call -
如何用这个问题为你投票?
标签: asp.net-core blazor-webassembly