Проверка ошибок при скачивании файла

Качаю файлы следующим образом:

            byte[] buf = new byte[4096];
            Int64 bytesTranfered = 0;
            int iter = 0;
            do
            {
                bytesAvaliable = size - bytesTranfered;
                if (bytesAvaliable > 0)
                {
                    bytesRead = responseStream.Read(buf, 0, buf.Length);
                    if (bytesRead > 0)
                    {
                        stream.Write(buf, 0, bytesRead);
                        bytesTranfered += bytesRead;
                        if (WorkProgress != null && progressUpdateInterval == 0 || iter++ >= progressUpdateInterval)
                        {
                            WorkProgress.Invoke(this, bytesTranfered);
                            iter = 0;
                        }
                    }
                }
                else
                    bytesRead = 0;
            } 
            while (bytesAvaliable > 0 && !stopped);

Всё качается, всё работает, хэш сходится.
Но как узнать об ошибке, если она, вдруг, произойдёт? Например, если скачается меньше, чем было запрошено?

Проверить в конце сколько скачалось?

а сразу в responseStream.Read(buf, 0, buf.Length) нельзя? Зачем качать лишнее, если ошибка уже произошла? Разве это никак иначе не отследить?
Только сегодня заметил, что эта фигня, почему-то, всегда возвращает 3783, хотя запрашивается 4096 :thinking:
Оставил 1 поток. Теперь при первом вызове возвращает 3788, а при последующих 4096.
Почему?

По-моему может быть примерно так, что Read отдает то, что сейчас доступно в буфере стрима (что может быть меньше запрошенного), а потом по сети приходят еще данные.

Так что лучше проверять когда понятно, что больше ничего нет.

Вообще я бы не изобретал велосипед, а использовал готовые HttpClient или WebClient.

Примеры:
https://docs.microsoft.com/en-us/dotnet/api/system.net.webclient.downloadprogresschanged
https://stackoverflow.com/a/46497896/964478

Чем это отличается от моего способа и как там делается проверка на ошибки?

Тем что самому не надо думать как правильно читать стрим )

Ошибка будет либо в выпавшем исключении, либо в случае Download***Async методов вебклиента — в свойстве в данных событий Download***Completed.

а что там думать-то? :grinning:

А как именно проверяется ошибка?
Я так понимаю, что он сначала всё докачивает, а потом сверяется с размером файла (или чанка), как вы ранее говорили.
Если так, то я не вижу никаких преимуществ. Лучше уж самостоятельно размер проверять.
К тому же, WebClient, вроде, в стрим не может качать. По-этому, он автоматически отпадает.
А в HttpClientе я не пойму

public static class StreamExtensions
{
    public static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default) {
        if (source == null)
            throw new ArgumentNullException(nameof(source));
        if (!source.CanRead)
            throw new ArgumentException("Has to be readable", nameof(source));
        if (destination == null)
            throw new ArgumentNullException(nameof(destination));
        if (!destination.CanWrite)
            throw new ArgumentException("Has to be writable", nameof(destination));
        if (bufferSize < 0)
            throw new ArgumentOutOfRangeException(nameof(bufferSize));

        var buffer = new byte[bufferSize];
        long totalBytesRead = 0;
        int bytesRead;
        while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) {
            await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
            totalBytesRead += bytesRead;
            progress?.Report(totalBytesRead);
        }
    }
}

где тут, собственно, проверка на то, что пришло столько же сколько было запрошено?
Если я правильно понял, тут ошибки чтения/записи никак не проверяются :thinking: У меня, вроде, то же самое написано, только без наворотов.