c# - WebClient UploadFileAsync 正在进行报告中的奇怪行为

标签 c# webclient system.net

我需要一些关于奇怪的 WebClient.UploadFileAsync() 行为的帮助。 我正在使用 POST 方法将文件上传到远程 HTTP 服务器 (nginx)。 POST 通过 PHP 脚本(地址指的是)进行处理。

我有这个简单的代码

public void uploadFile(string filePath)
{
    webClient = new WebClient();
    webClient.Credentials = new NetworkCredential(Constant.HTTPUsername,Constant.HTTPPassword);
    webClient.Headers.Add("Test", TestKey);
    webClient.UploadProgressChanged += webClient_UploadProgressChanged;
    webClient.UploadFileCompleted += webClient_UploadFileCompleted;

    try
    {
        webClient.UploadFileAsync(new Uri(Address), "POST", filePath);
    }
    catch (Exception error)
    {
        throw new CustomException(error.Message);
    }
}

在 UploadProgressChanged 中,我只是用给定的 ProgressPercentage 更新了一个进度条。 第一个问题是报告的进度百分比,无论文件大小如何:

[17.38.14] Progress: 0 Bytes Sent: 175 / 269264
[17.38.14] Progress: 1 Bytes Sent: 8367 / 269264
[17.38.14] Progress: 3 Bytes Sent: 16559 / 269264
[17.38.14] Progress: 4 Bytes Sent: 24751 / 269264
[17.38.14] Progress: 6 Bytes Sent: 32943 / 269264
[17.38.14] Progress: 7 Bytes Sent: 41135 / 269264
[17.38.14] Progress: 9 Bytes Sent: 49327 / 269264
[17.38.14] Progress: 10 Bytes Sent: 57519 / 269264
[17.38.14] Progress: 12 Bytes Sent: 65711 / 269264
[17.38.14] Progress: 13 Bytes Sent: 73903 / 269264
[17.38.14] Progress: 15 Bytes Sent: 82095 / 269264
[17.38.14] Progress: 16 Bytes Sent: 90287 / 269264
[17.38.14] Progress: 18 Bytes Sent: 98479 / 269264
[17.38.15] Progress: 19 Bytes Sent: 106671 / 269264
[17.38.15] Progress: 21 Bytes Sent: 114863 / 269264
[17.38.15] Progress: 22 Bytes Sent: 123055 / 269264
[17.38.15] Progress: 24 Bytes Sent: 131247 / 269264
[17.38.15] Progress: 25 Bytes Sent: 139439 / 269264
[17.38.15] Progress: 27 Bytes Sent: 147631 / 269264
[17.38.16] Progress: 28 Bytes Sent: 155823 / 269264
[17.38.16] Progress: 30 Bytes Sent: 164015 / 269264
[17.38.16] Progress: 31 Bytes Sent: 172207 / 269264
[17.38.16] Progress: 33 Bytes Sent: 180399 / 269264
[17.38.16] Progress: 35 Bytes Sent: 188591 / 269264
[17.38.16] Progress: 36 Bytes Sent: 196783 / 269264
[17.38.17] Progress: 38 Bytes Sent: 204975 / 269264
[17.38.17] Progress: 39 Bytes Sent: 213167 / 269264
[17.38.17] Progress: 41 Bytes Sent: 221359 / 269264
[17.38.17] Progress: 42 Bytes Sent: 229551 / 269264
[17.38.17] Progress: 44 Bytes Sent: 237743 / 269264
[17.38.17] Progress: 45 Bytes Sent: 245935 / 269264
[17.38.17] Progress: 47 Bytes Sent: 254127 / 269264
[17.38.18] Progress: 48 Bytes Sent: 262319 / 269264
[17.38.18] Progress: 49 Bytes Sent: 269220 / 269264
[17.38.18] Progress: 50 Bytes Sent: 269264 / 269264
[17.38.25] Progress: -50 Bytes Sent: 269264 / 269264
[17.38.25] Progress: 100 Bytes Sent: 269264 / 269264
[17.38.25] FileCompleted event raised!

因此,在网络上搜索后,我发现从 50->100 的跳跃只是百分比报告中的一个设计选择。所以我对此很满意。 奇怪的是,即使在 50%(当整个文件被发送时),网络接口(interface)仍然产生流量并且仍在上传。 事实上,从上面日志中的时间可以看出,发送文件后需要 7 秒才能引发 UploadFileCompletedEvent。实际上,与此同时,我仍在通过 HTTP 发送文件。

这里的问题是我无法可靠地更新我的 UI:进度条会增长到 50%,但随后它会卡住等待上传完成(这是一个不好的行为,因为对于大文件,这个时间会显着增长).

问题是:我怎样才能可靠地让用户了解文件上传进度?

谢谢。

附言该方法工作得很好,文件已正确上传到远程服务器。唯一的问题是进度报告。

最佳答案

我刚刚发现了问题:它在基本的 HTTP 身份验证中。出于某种奇怪的原因,即使我指定了凭据,WebClient 也提交了第一个 POST 请求,而没有在 HTTP header 中指定凭据。在服务器回复 auth-request 后,它提交第二个 POST 请求,正确指定凭据。在这 2 次重试中,我的应用程序发送了文件 2 次! (这就是为什么即使在文件完全发送后我仍然有上传事件的原因)

解决方案是通过手动添加身份验证 header (并删除 WebClient.Credentials.. 行)来强制执行 HTTP 基本身份验证:

string authInfo = userName + ":" + userPassword;
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
req.Headers["Authorization"] = "Basic " + authInfo;

这样,第一个(也是唯一一个)POST 请求将使用 Authentication header 正确提交,并且报告进度正确(仅用于共享,我在进度条中将进度报告为 (e.ProgressPercentage * 2) 原因以上。

关于c# - WebClient UploadFileAsync 正在进行报告中的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13420983/

相关文章:

c# - 使用 EF Code First 登录到数据库

c# - 如何使用 WebClient DownloadStringAsync 来避免卡住 UI?

c# - Windows 8 的 WebClient 替代品?

代理服务器的 C# 性能(与 C++ 相比)

c# - 有没有办法将 C# 序列化对象读入 Python?

c# - 如何对自定义对象创建的属性使用 Blazor ValidationMessage

c# - 密码记住不能按需要工作

c# - 使用 JSON Web 服务时出现奇怪的字符

c# - 构建服务器上的 System.Net.Http 版本错误

c# - 如何让 HttpHeaders.TryGetValues() 返回多个值?