Reputation: 19567
I have a C# console app, which downloads the files from web-sites. Here are my methods:
public bool DownloadFile(string fileUri, string filePath)
{
using (var response = _GetResponce(fileUri)) {
if (response.StatusCode != HttpStatusCode.OK) {
return false;
}
using (var responseStrm = response.GetResponseStream()) {
using (var fileStrm = new FileStream(filePath, FileMode.OpenOrCreate)) {
var buffer = new byte[CommonConstants.StreamBufferSize];
int bytesRead = responseStrm.Read(buffer, 0, CommonConstants.StreamBufferSize);
while(bytesRead > 0) {
fileStrm.Write(buffer, 0, bytesRead);
bytesRead = responseStrm.Read(buffer, 0, CommonConstants.StreamBufferSize);
}
}
}
}
private HttpWebResponse _GetResponce(string requestedUri, string method = "GET")
{
var request = (HttpWebRequest)WebRequest.Create(requestedUri);
request.Method = method;
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13";
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Headers[HttpRequestHeader.AcceptLanguage] = "ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3";
request.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate";
request.Headers[HttpRequestHeader.AcceptCharset] = "windows-1251,utf-8;q=0.7,*;q=0.7";
return (HttpWebResponse)request.GetResponse();
}
I tried to increase the buffer size, to no avail. If I add threads, can it increase download speed?
Upvotes: 2
Views: 3505
Reputation: 98736
Have you tried buffering more data before writing it to the file? In general you want to be polling the socket as quickly as possible -- it's been my experience that even if many bytes are available for reading, only a relatively small chunk of them may be returned, meaning the socket throughput ends up tied to the overhead of the rest of the loop, which could be significant.
Try this code and see if you get a measurable improvement:
using (var fileStrm = new FileStream(filePath, FileMode.OpenOrCreate))
using (var responseStrm = response.GetResponseStream()) {
const int BufferSize = 1 * 1024 * 1024 + CommonConstants.StreamBufferSize;
var buffer = new byte[BufferSize];
int offset, bytesRead;
do { // Until we've read everything
offset = 0;
do { // Until the buffer is very nearly full or there's nothing left to read
bytesRead = responseStrm.Read(buffer, offset, BufferSize - offset);
offset += bytesRead;
} while (bytesRead != 0 && offset + CommonConstants.StreamBufferSize < BufferSize);
// Empty the buffer
if (offset != 0) {
fileStrm.Write(buffer, 0, offset);
}
} while (bytesRead != 0);
}
Also, if you're accepting gzip and zlib streams, you'll need to turn on decompression(!):
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
Upvotes: 1
Reputation: 100312
Depending on the server, you might gain some speed downloading the file with several segments.
For that you can use request.AddRange
and have different threads to download the same file. Note that when you write the data to a local file you must start in the correct offset.
This is something that most download managers do.
Note that some servers will not allow that.
Upvotes: 1