Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
Bretbas
Каждому свое
521 / 207 / 81
Регистрация: 05.08.2013
Сообщений: 1,611
Завершенные тесты: 2
1

Прогресс для Upload файла на сервер используя HttpClient

24.05.2018, 14:49. Просмотров 1287. Ответов 3

Подскажите пожалуйста, как можно сделать прогресс Upload файла на сервер с помощью HttpClient?
В Download я сделал прогресс, путем добавления в запрос параметра HttpCompletionOption.ResponseHeadersRead, чтобы получить только заголовки контента.
На основе полученного из заголовков размера контента, и самого потока данных(NetworkStream), я сделал прогресс для Скачивания(Download) файла.

Не могу представить как прогресс сделать с Upload(загрузкой) файла на сервер с помощью HttpClient. Слышал, что там нужно наследоваться от HttpContent и все такое, но только мельком.

Может кто знает?

Добавлено через 19 часов 33 минуты
Неужели никто не знает?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
24.05.2018, 14:49
Ответы с готовыми решениями:

Upload to OneDrive: ошибка 404 при загрузке файла на сервер
День добрый. На сервере OneDrive (Microsoft) имеется некий файл. Этот файл открыт для общего...

HttpClient размер файла для расчета прогресса
Есть такой код var httpClient = new HttpClient(); ...

Прогресс бар при скачивании файла используя HttpWebRequest/HttpWebResponse
есть код void DownloadFile(string sSourceURL, string sDestinationPath) { ...

Реализация Upload файла на сервер
Привет всем! Помогите с проблемой, необходимо реализовать закачку файла на сервер. Киньте...

Чтение данных файла при его upload'е на сервер !
Привет всем ! У меня такая проблема. Нужно сделать upload файла на сайт. Сделал форму, прописал...

3
kingzfate
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 829
Завершенные тесты: 1
24.05.2018, 15:03 2
Bretbas, ну вот как вариант через httpClientFactory
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void HttpSendProgress(object sender, HttpProgressEventArgs e)
    {
        HttpRequestMessage request = sender as HttpRequestMessage;
        Console.WriteLine(e.BytesTransferred);
    }
 
    private void Window_Loaded_1(object sender, RoutedEventArgs e)
    {
        ProgressMessageHandler progress = new ProgressMessageHandler();
        progress.HttpSendProgress += new EventHandler<HttpProgressEventArgs>(HttpSendProgress);
 
        HttpRequestMessage message = new HttpRequestMessage();
        StreamContent streamContent = new StreamContent(new FileStream("e:\\somefile.zip", FileMode.Open));
 
        message.Method = HttpMethod.Put;
        message.Content = streamContent;
        message.RequestUri = new Uri("{Here your link}");
 
        var client = HttpClientFactory.Create(progress);
 
        client.SendAsync(message).ContinueWith(task =>
        {
            if (task.Result.IsSuccessStatusCode)
            { 
 
            }
        });
    }
0
Bretbas
Каждому свое
521 / 207 / 81
Регистрация: 05.08.2013
Сообщений: 1,611
Завершенные тесты: 2
24.05.2018, 18:23  [ТС] 3
kingzfate, Это ASP.NET? Не, мне нужно для WPF.
0
Bretbas
Каждому свое
521 / 207 / 81
Регистрация: 05.08.2013
Сообщений: 1,611
Завершенные тесты: 2
27.05.2018, 09:37  [ТС] 4
Лучший ответ Сообщение было отмечено Почтальон как решение

Решение

Очень печально, что на этом форуме никто не отвечает на более сложные вопросы, которые не входят в состав вопросов "Hello, world".

Порыскав в интернете, перечитав множество информации, пришлось написать самому все.
Итак, чтобы сделать оповещение о прогрессе загрузки файла на сервер(Upload), я написал наследника класса StreamContent:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public delegate void ProgressHandler(long bytes, long currentBytes, long totalBytes); 
 
class ProgressStreamContent : StreamContent
{
    private const int DEFAULT_BUFFER_SIZE = 4096;
 
    public event ProgressHandler ProgressChanged = delegate { };
 
    private long currentBytes = 0;
    private long totalBytes = -1;
 
 
    public Stream InnerStream { get; }
    public int BufferSize { get; }
 
    public ProgressStreamContent(Stream innerStream, int bufferSize = DEFAULT_BUFFER_SIZE) :
        base(innerStream, bufferSize)
    {
        InnerStream = innerStream ?? throw new ArgumentNullException(nameof(innerStream));
        BufferSize = bufferSize > 0 ? bufferSize : throw new ArgumentOutOfRangeException(nameof(bufferSize));
    }
 
    private void ResetInnerStream()
    {
        if (InnerStream.Position != 0)
        {
            // Если внутренний поток нужно считать повторно, то этот внутренний поток должен поддерживать
            // возврат каретки(например FileStream), иначе внутренний поток не может быть считан повторно
            // в целевой поток(например NetworkStream)
            if (InnerStream.CanSeek)
            {
                InnerStream.Position = 0;
                currentBytes = 0;
            }
            else
                throw new InvalidOperationException("The inner stream has already been read!");
        }
    }
 
    protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        if (stream == null) throw new ArgumentNullException(nameof(stream));
 
        // Сбрасываем состояние внутреннего потока
        ResetInnerStream();
 
        // Если общее количество байт еще не получено, то пытаемся получить
        // его из заголовков контента
        if (totalBytes == -1)
            totalBytes = Headers.ContentLength ?? -1;
 
        // Если общее количество байт еще не найдено, то пытаемся
        // вычислить его из потока
        if (totalBytes == -1 && TryComputeLength(out var computedLength))
            totalBytes = computedLength == 0 ? -1 : computedLength;
 
        // Если общее количество байт отрицательное значение, то
        // присваеваем ему -1, идентифицирующее о невалидном общем количестве байт
        totalBytes = Math.Max(-1, totalBytes);
 
        // Начинаем читать внутренний поток
        var buffer = new byte[BufferSize];
        var bytesRead = 0;
        while ((bytesRead = await InnerStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {
            stream.Write(buffer, 0, bytesRead);
            currentBytes += bytesRead;
 
            // Генерируем событие ProgressChanged, чтобы оповестить о текущем прогрессе считывания
            ProgressChanged(bytesRead, currentBytes, totalBytes);
        }
    }
 
    protected override bool TryComputeLength(out long length)
    {
        var result = base.TryComputeLength(out length);
        totalBytes = length;
        return result;
    }
 
    protected override void Dispose(bool disposing)
    {
        if (disposing)
            InnerStream.Dispose();
 
        base.Dispose(disposing);
    } 
}
Теперь использование:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public async Task UploadAsync(Uri uri, Stream stream, IProgress<float> progress, CancellationToken cancelToken = default(CancellationToken))
{
    if(uri == null) throw new ArgumentNullException(nameof(uri ));
    if(stream == null) throw new ArgumentNullException(nameof(stream));
    if(progress == null) throw new ArgumentNullException(nameof(progress));
 
    // Название файла
    var fileName = Path.GetFileName(((FileStream)stream).Name);
 
    // Подготавливаем контент потока
    var streamContent = new ProgressStreamContent(stream);
    streamContent.ProgressChanged += (bytes, currBytes, totalBytes) => progress.Report((float)currBytes / totalBytes * 100);
 
    // Данные на отправление
    var content = new MultipartFormDataContent();
    content.Add(streamContent, "file", fileName);
 
    try
    {
        using (var client = new HttpClient())
        {
            // Здесь скорее всего устанавливаем всякие заголовки
            // ...
 
            // Посылаем Post запрос
            var response = await client.PostAsync(uri, content, cancelToken);
 
            // Проверяем статус ответа
            switch (response.StatusCode)
            {
                /* Здесь проверяем статус ответа и предпринимаем действия */
            }
        }
    }
    catch (HttpRequestException)
    {
        throw new ConnectionErrorException("Ошибка соединения");
    }
}
Впринципе все
1
27.05.2018, 09:37
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.05.2018, 09:37

Как написать CGI на С или на Delphi для Upload File на сервер?
Как написать CGI на С или на Delphi для Upload File на сервер,

Upload file. Нужна ли база данных для загрузки файла?
Тут на сайте есть объяснение как его загружать, но...по-моему много лишнего. Нужна ли база данных...

Прогресс бар для отображения процесса скачивания файла
Сделал апдейтер для своей игры(Использовал game maker). Но иногда патчи бывают очень большие. А он...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru