我有以下代码来监控上传过程。我正在使用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),进度条预期0-100)。然后我不得不钳制结果值。所以我想出了这个:
(int)Clamp((float)e2.ProgressPercentage / 50 * 100, 0, 100)
虽然现在这样做很好,但我想知道为什么我需要破解我的方式才能使它工作。我做错了吗?
更新:我决定不依赖e.ProgressPercentage
并自行进行计算:
UploadProgressBar.Value = (int)(e2.BytesSent / (float)e2.TotalBytesToSend * 100);
答案 0 :(得分:0)
这是设计的。原因是
当您进行上传时,服务器也可以发送数据作为对上传的响应。通常,对于任何HTTP请求都是如此。考虑一个表单上传一堆输入和服务器发送一大堆数据,也许是一个SQL服务器数据库报告。 在所有这些情况下,我们将上传和下载设置为50%和50%。 因此,如果服务器没有发送任何数据,那么它将直接从50跳到100
同时检查this thread此方法可能存在的问题。
另一种解决方案
可视化上传的正确值的另一个选项是使用UploadProgressChangedEventArgs对象的另外两个属性 - BytesSent,TotalBytesToSend - 并自己进行计算。如需参考,请查看the examples section。
编辑: 我无法找到任何记录以这种方式实现这一点的原因是什么,但这里是负责此行为的代码:
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
答案 1 :(得分:0)
我能够重现同样的东西,包括奇怪的掉落。
请考虑使用来自单独线程的FtpWebRequest
。这样,您就可以完全控制上传进度。
请参阅我的回答 How can we show progress bar for upload with FtpWebRequest