Для того что бы скачать файл по протоколу http на C# потребуется написать всего несколько строчек и подключить пространство имен System.Net.
Самый простой, но не самый наглядный способ.
Просто как две строчки написать:
WebClient webClient = new WebClient();
webClient.DownloadFile("http://mysite.com/myfile.txt", @"c:\myfile.txt");
Но никакого отображения процесса загрузки файла не происходит, что конечно же не устраивает нетерпеливых пользователей.
Скачка файла с отображением процесса загрузки.
Для загрузки файла по http не блокируя при этом основного потока необходимо воспользоваться методом DownloadFileAsync. Также можно обработать событие DownloadProgressChanged для индикации процесса загрузки файла и событие DownloadFileCompleted для определения момента, когда файл будет полностью загружен.
private void btnDownload_Click(object sender, EventArgs e)
{
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
webClient.DownloadFileAsync(new Uri("http://mysite.com/myfile.txt"), @"c:\myfile.txt");
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
private void Completed(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Download completed!");
}
Скачка файла с отображением процесса загрузки при помощи WebRequest.
Для того что бы скачать файл с помощью класса WebRequest потребуется немного больше усилий чем в способах описанных выше и особой выгоды от этого не будет, но рассмотреть их тоже стоит.
Для этого необходимо послать запрос по необходимому адресу и в ответе будет содержаться ссылка на поток с данными:
HttpWebRequest _req = (HttpWebRequest) WebRequest.Create(“http://mysite.com/myfile.txt”);
WebResponse _response = _req.GetResponse();
Stream _stream = _response.GetResponseStream();
Для того что бы сохранить данные на диске необходимо в цикле прочитать содержимое потока полученного в результате выполнения запроса, например вот так:
FileStream _fs = new FileStream(“myfile.txt”, FileMode.Create)
int _bytesRead = 1;
while (_bytesRead != 0)
{
byte[] buffer = new byte[1024];
_bytesRead = _stream.Read(buffer, 0, buffer.Length);
_fs.Write(buffer, 0, buffer.Length);
}
Запустив все эти действия в отдельном потоке, в основном потоке можно отображать процесс загрузки. Так как работать с визуальными компонентам инеобходимо из потока в котором они создавались, то для изменения например ProgressBar стоит воспользоваться методом Invoke():
public delegate void dClose();
private delegate void dProgressInit(ProgressBar aPb, Int32 aMaxValue);
private delegate void dProgressValue(ProgressBar aPb, Int32 aValue);
private void ProgressInit(ProgressBar aPb, Int32 aMaxValue)
{
aPb.Maximum = aMaxValue;
}
private void ProgressValue(ProgressBar aPb, Int32 aValue)
{
aPb.Value = aValue;
}
private void DownloadFiles()
{
HttpWebRequest _req = (HttpWebRequest)WebRequest.Create(item.Link);
WebResponse _response = _req.GetResponse();
Invoke(new dProgressInit(ProgressInit), new object[] { pbBytes,(Int32)_response.ContentLength });
Invoke(new dProgressValue(ProgressValue), new object[] { pbBytes, 0 });
using (Stream _stream = _response.GetResponseStream())
{
using (FileStream _fs = new FileStream(@"c:\test.txt",FileMode.Create))
{
int _bytesRead = 1;
while (_bytesRead != 0)
{
byte[] buffer = new byte[32768];
_bytesRead = _stream.Read(buffer, 0, buffer.Length);
_fs.Write(buffer, 0, buffer.Length);
buffer = null;
Invoke(new dProgressValue(ProgressValue), new object[] { pbBytes, pbBytes.Value + _bytesRead });
Invoke(new dClose(pbBytes.Refresh));
}
}
}
}
Особое внимание в этом способе загрузки следует уделить размеру буфера (byte[] buffer = new byte[32768];) т.к. это влияет на скорость и качество загрузки. Чем меньше буфер, тем необходимо потратить больше ресурсов (времени) на запрос следующей части, но меньше вероятность сбоя подключения и соответственно наоборот.