Подтвердить что ты не робот

WebClient UploadFileAsync странное поведение в процессе отчетности

Мне нужна помощь со странным поведением WebClient.UploadFileAsync(). Я загружаю файл на удаленный HTTP-сервер (nginx) метод POST. POST обрабатывается через PHP script (к которому относится адрес).

У меня есть этот простой код

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 я просто обновляю progressBar с данными 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% (когда весь файл был отправлен), сетевой интерфейс все еще генерирует трафик и все еще загружается. Фактически, как вы можете видеть из времени в вышеприведенном журнале, после отправки файла требуется 7 секунд, чтобы поднять файл UploadFileCompletedEvent. Фактически, я все равно отправляю файл через HTTP.

Проблема в том, что я не могу достоверно обновлять свой интерфейс: индикатор выполнения будет расти до 50%, но тогда он будет застревать в ожидании завершения загрузки (и это плохое поведение, поскольку с большим файлом это время значительно увеличивается).

Вопрос в следующем: как я могу надежно обновить пользователя о ходе загрузки файла?

Спасибо.

P.S. метод работает отлично, и файл правильно загружен на удаленный сервер. Единственная проблема связана с отчетами о проделанной работе.

4b9b3361

Ответ 1

Я только что нашел проблему: это в базовой HTTP-аутентификации. По какой-то странной причине, даже если я указываю Credentials, WebClient отправляет первый запрос POST без указания учетных данных в заголовке HTTP. После того, как сервер отвечает с помощью auth-request, он отправляет второй запрос POST, правильно определяющий учетные данные. В этих 2 повторных попытках мое приложение отправляет файл 2 раза! (Вот почему я испытал активность загрузки даже после того, как файл был полностью отправлен)

Решение состоит в том, чтобы принудительно выполнить базовую аутентификацию HTTP, вручную добавив заголовок аутентификации (и удалив строку WebClient.Credentials..:

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

Таким образом, первый (и только) запрос POST будет правильно отправлен с заголовком проверки подлинности, а ход отчета будет выполнен правильно (только для совместного использования, я сообщаю о прогрессе в моей панели прогресса как (e.ProgressPercentage * 2) по причине выше.

Ответ 2

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

Поместите это в начале вашего запроса на отправку с помощью e.ProgressPercentage * 2 для целей отчета о ходе выполнения.