i具有以下代码来监视上传过程。我正在使用e.ProgressPercentage
跟踪当前的进度,但是它返回错误的值。
using (WebClient client = new WebClient())
{
client.Credentials = new NetworkCredential(DataIO.FTP.Username, DataIO.FTP.Password);
Uri uri = new Uri($"ftp://{DataIO.FTP.Server}/{DataIO.FTP.UploadDir}/{DataIO.SelectedOutputArchive}.tar.gz");
client.UploadProgressChanged += new UploadProgressChangedEventHandler(delegate (object s2, UploadProgressChangedEventArgs e2) {
ProgressLabel.Invoke((MethodInvoker)delegate
{
ProgressLabel.Text = $"{(e2.BytesSent / 1024).ToString()} KB / {(e2.TotalBytesToSend / 1024).ToString()} KB";
});
UploadProgressBar.Invoke((MethodInvoker)delegate
{
UploadProgressBar.Value = e2.ProgressPercentage; // returns 0-50
//UploadProgressBar.Value = (int)Clamp((float)e2.ProgressPercentage / 50 * 100, 0, 100);
});
Debug.WriteLine(e2.ProgressPercentage);
});
client.UploadFileCompleted += new UploadFileCompletedEventHandler(delegate {
this.Invoke((MethodInvoker)delegate
{
this.Text = "Upload: Success";
});
Thread.Sleep(2000);
this.Invoke((MethodInvoker)delegate
{
this.Close();
});
});
client.UploadFileAsync(uri, "STOR", localFilePath);
}
我尝试在输出窗口中调试它,返回的值就是这样:
0
0
1
0
1
0
1
1
1
2
2
1
2
2
3
3
2
3
3
...
49
49
50
49
100
49
49
这些后跳不一定很重要,但是从49跳到100是。
我以为它总是在0-50之间返回(意识到它的提高50之后(。因此,我需要将其扩展到0-100。这起作用了,但随后从49跃升至100。缩放期望从0-50开始,并收到100次中断(导致溢出结果(200(,ProgressBar期望为0-100(。然后,我不得不夹紧结果值。所以我想到了:
(int)Clamp((float)e2.ProgressPercentage / 50 * 100, 0, 100)
虽然现在正常工作,但我想知道为什么我需要破解使它起作用的方式。我做错了吗?
更新:我决定不依靠e.ProgressPercentage
并自己进行计算:
UploadProgressBar.Value = (int)(e2.BytesSent / (float)e2.TotalBytesToSend * 100);
这是设计。原因是
上传时,服务器也可以作为对上传的响应发送数据。通常,对于任何HTTP请求,这都是正确的。考虑上传一堆输入的表单,然后服务器发送一堆数据,也许是SQL Server数据库报告。 在所有这些情况下,我们将上载并下载为50%和50%。 因此,如果服务器未发送任何数据,则它将直接跳到50到100
来源:https://social.msdn.microsoft.com/forums/en-us/9ab5a1b4-c30d-4dbb-bbb-bebe-a00ef8e72029/problems-webclientupploploasync?forumeasync?forum=netfxnetfxnetfxnetcom 检查此线程是否有此方法可能的问题。
另一种解决方案
可视化上载的正确值的另一个选项是使用uploadprogresschangedeventargs对象的另外两个属性 - bytessent,totalbytestosend-并自己进行计算。作为参考,请检查示例部分。
编辑:我找不到记录以这种方式实施此目的的任何地方,但是这里是负责此行为的代码:
private void PostProgressChanged(AsyncOperation asyncOp, ProgressData progress) {
if (asyncOp != null && progress.BytesSent + progress.BytesReceived > 0)
{
int progressPercentage;
if (progress.HasUploadPhase)
{
if (progress.TotalBytesToReceive < 0 && progress.BytesReceived == 0)
{
progressPercentage = progress.TotalBytesToSend < 0 ? 0 : progress.TotalBytesToSend == 0 ? 50 : (int)((50 * progress.BytesSent) / progress.TotalBytesToSend);
}
else
{
progressPercentage = progress.TotalBytesToSend < 0 ? 50 : progress.TotalBytesToReceive == 0 ? 100 : (int) ((50 * progress.BytesReceived) / progress.TotalBytesToReceive + 50);
}
asyncOp.Post(reportUploadProgressChanged, new UploadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState, progress.BytesSent, progress.TotalBytesToSend, progress.BytesReceived, progress.TotalBytesToReceive));
}
else
{
progressPercentage = progress.TotalBytesToReceive < 0 ? 0 : progress.TotalBytesToReceive == 0 ? 100 : (int) ((100 * progress.BytesReceived) / progress.TotalBytesToReceive);
asyncOp.Post(reportDownloadProgressChanged, new DownloadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState, progress.BytesReceived, progress.TotalBytesToReceive));
}
}
}
来源:https://referencesource.microsoft.com/system/net/system/net/webclient.cs.html#2966
我也能够再现相同的重现,包括奇怪的滴。
考虑使用来自单独线程的FtpWebRequest
。这样,您可以完全控制上传进度。
请参阅我的答案我们如何显示进度栏以使用ftpwebrequest上传。