Reputation: 115
I have an issue downloading a 400MB+ file using C#'s HttpClient ReadAsStreamAsync - the issue is that only around 213864187 bytes are being read out of 427724800 and then
read = await stream.ReadAsync(buffer, 0, buffer.Length, token)
keeps returning 0 for no obvious reason.
Anyone had similar problem?
using (var stream = await response.Content.ReadAsStreamAsync()) {
var totalRead = 0L;
var buffer = new byte[4096];
var moreToRead = true;
const int CHUNK_SIZE = 4096;
var fileStream = File.Create(filename, CHUNK_SIZE);
int bytesRead;
do {
token.ThrowIfCancellationRequested();
var read = await stream.ReadAsync(buffer, 0, buffer.Length, token);
if (read == 0) {
moreToRead = false;
this.Percentage = 100;
if (fileStream != null) {
fileStream.Close();
fileStream.Dispose();
}
} else {
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
bytesRead = stream.Read(buffer, 0, CHUNK_SIZE);
if (bytesRead > 0) {
fileStream.Write(buffer, 0, bytesRead);
}
// Update the percentage of file downloaded
totalRead += read;
if (canReportProgress) {
var downloadPercentage = ((totalRead * 1d) / (total * 1d)) * 100;
var value = Convert.ToInt32(downloadPercentage);
this.Percentage = value;
this.BytesReceived = totalRead;
}
}
}
while (moreToRead);
}
Upvotes: 1
Views: 3558
Reputation: 42225
There's something strange going on around this bit:
buffer.ToList().CopyTo(0, data, 0, read);
bytesRead = stream.Read(buffer, 0, CHUNK_SIZE);
if (bytesRead > 0) {
fileStream.Write(buffer, 0, bytesRead);
}
I'd expect you to write the bytes you just read into the fileStream
- i.e. fileStream.Write(buffer, 0, read)
on its own. However you copy the buffer to a data
array (which is never used again), then read from the stream again into buffer
(this time synchronously), and write that.
So you're throwing away half of the downloaded bytes. No wonder "only around 213864187 bytes are being read out of 427724800"!
Also, use a using
block for your fileStream
, rather than using an explicit .Dispose()
call. Also, if you're copying one array to another, use Array.Copy
rather than array.ToList().CopyTo(...)
.
Upvotes: 6