Download Multiple file, one by one using DownloadFileAsync in C# - c#

How can I download multiple files, one by one. Using my code.
//Download File
public void DownloadFile(string url, string folderfile)
{
WebClient wc = new WebClient();
try
{
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadChanged);
wc.DownloadFileAsync(new Uri(url), folderfile);
}
catch (Exception ex)
{
MessageBox.Show("Error: \n\n" + ex.Message);
}
}
private void DownloadChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100.0;
int percente = int.Parse(Math.Truncate(percentage).ToString());
PBar.Value = percente;
progress.Text = percente + " %";
size.Text = string.Format("{0} MB / {1} MB", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
}
private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("Erro: " + e.Error.Message);
}
else
{
info.Text = "Download Success.";
}
}
public void CheckFileDownload()
{
string urlGame = "http://localhost/";
string Game = "Game.exe";
string Support = "Support.Xml";
string Info = "Info.xml";
if (!File.Exists(Game))
{
//Download Game
DownloadFile(urlGame + Game, Game);
info.Text = "Downloading: " + Game;
//If the game is downloading full
DownloadFile(urlGame + Info, Info);
DownloadFile(urlGame + Support, Support);
info.Text = "Updating information...";
}
}
private void Launcher_Load(object sender, EventArgs e)
{
CheckFileDownload();
}
Because I need to update the checkpoint file, after you download the Game.
I looked at several topics, but without success.
Thank everyone who helped me ... Sorry for my bad English
Thank you to all that help me. I will be very grateful...

If performance is not an issue, you can use DownloadFile and then it will download them in the sequence you specify and you don't need to bother with all the overlapping asynchronous operations. Since you're only downloading 3 files, the time savings of async coding is probably not worth it.
Alternately you could define flags for each file you intend to download (at the class level, not inside any of your functions), which could be in a Dictionary or just 3 bool variables. In DownloadFilAsync documentation note the userToken argument, which you use to identify which of the 3 files is done downloading. Use that to set the completed flags; then when the last download is complete, you carry on with whatever happens next.

Related

When using async task and await to download files why the first file is taking almost 30 seconds to download?

then after the first file it's downloading all the rest of the files in the links fast but the first one take a lot of time.
the button click event to start the downloading.
private async void btnStart_Click(object sender, EventArgs e)
{
CreateDownloadFolders createDownloadFolders = new CreateDownloadFolders();
createDownloadFolders.GenerateDownloadFolders(textBoxRadarPath.Text, textBoxSatellitePath.Text);
lblStatus.Text = "Preparing Downloads";
loadingLabel1.Visible = true;
radar.PrepareLinks();
await satellite.DownloadSatelliteAsync();
downloadLinks.AddRange(radar.links);
downloadLinks.AddRange(satellite.links);
loadingLabel1.Visible = false;
for (int i = 0; i < downloadLinks.Count; i++)
{
if (downloadLinks[i].Contains("Radar"))
{
lblStatus.Text = "Downloading radar images";
await DownloadFiles(downloadLinks[i], Path.Combine(textBoxRadarPath.Text,
$"RadarImage{countRadarImages + 1}.gif"));
countRadarImages++;
}
else
{
lblStatus.Text = "Downloading satellite images";
await DownloadFiles(downloadLinks[i], Path.Combine(textBoxSatellitePath.Text,
$"SatelliteImage{countSatelliteImages + 1}.gif"));
countSatelliteImages++;
}
}
}
i used a break point and it's getting very fast to the for loop :
for (int i = 0; i < downloadLinks.Count; i++)
then i added another break point in the DownloadFiles method : and it's getting fast to the line :
await webClient.DownloadFileTaskAsync(URL, location);
this is the DownloadFiles method
public async Task DownloadFiles(string urlAddress, string location)
{
Stopwatch sw = new Stopwatch();
using (WebClient webClient = new WebClient())
{
webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0 Chrome");
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(((sender, e) => Completed(sender, e, sw)));
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) => ProgressChanged(sender, e, sw));
Uri URL = new Uri(urlAddress);
sw.Start();
try
{
savedFile = location;
await webClient.DownloadFileTaskAsync(URL, location);
}
catch (Exception ex)
{
string err = ex.Message;
}
}
}
but then it's not getting to the progress changed event and the completed event
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e, Stopwatch sw)
{
string downloadProgress = e.ProgressPercentage + "%";
string downloadSpeed = string.Format("{0} MB/s", (e.BytesReceived / 1024.0 / 1024.0 / sw.Elapsed.TotalSeconds).ToString("0.00"));
string downloadedMBs = Math.Round(e.BytesReceived / 1024.0 / 1024.0) + " MB";
string totalMBs = Math.Round(e.TotalBytesToReceive / 1024.0 / 1024.0) + " MB";
// Format progress string
string progress = $"{downloadedMBs}/{totalMBs} ({downloadProgress}) # {downloadSpeed}"; // 10 MB / 100 MB (10%) # 1.23 MB/s
textProgressBar1.Value = e.ProgressPercentage;
textProgressBar1.CustomText = progress;
}
private void Completed(object sender, AsyncCompletedEventArgs e, Stopwatch sw)
{
if (e.Cancelled == true)
{
sw.Stop();
}
if (e.Error != null)
{
filesCounter--;
File.Delete(savedFile);
if(filesCounter == 0)
{
lblStatus.Text = "Downloading Finished";
}
}
else
{
filesCounter--;
sw.Stop();
if (radar.links.Count == 0)
{
sw.Stop();
}
}
}
after the line
await webClient.DownloadFileTaskAsync(URL, location);
it's just hanging not freezing the application just hanging for almost 30 seconds and then start downloading the rest of the files very fast.
why at the first time it's hanging/waiting so much time and not downloading all the files?

Wait for DownloadFileAsync to finish downloading and then do something

So basically my DownloadFile is:
public void DownloadFile()
{
settings_btn.Enabled = false;
label1.Text = "Checking for updates...";
//Defines the server's update directory
string Server = "http://downloadurl/update/";
//Defines application root
string Root = AppDomain.CurrentDomain.BaseDirectory;
//Make sure version file exists
FileStream fs = null;
if (!File.Exists("pversion"))
{
using (fs = File.Create("pversion")){}
using (StreamWriter sw = new StreamWriter("pversion")){sw.Write("1.0");}
}
//checks client version
string lclVersion;
using (StreamReader reader = new StreamReader("pversion"))
{
lclVersion = reader.ReadLine();
}
decimal localVersion = decimal.Parse(lclVersion);
//server's list of updates
XDocument serverXml = XDocument.Load(#Server + "pUpdates.xml");
//The Update Process
foreach (XElement update in serverXml.Descendants("pupdate"))
{
string version = update.Element("pversion").Value;
string file = update.Element("pfile").Value;
decimal serverVersion = decimal.Parse(version);
string sUrlToReadFileFrom = Server + file;
string sFilePathToWriteFileTo = Root + file;
if (serverVersion > localVersion)
{
using (webClient = new WebClient())
{
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
// The variable that will be holding the url address (making sure it starts with http://)
Uri url = new Uri(sUrlToReadFileFrom);
// Start the stopwatch which we will be using to calculate the download speed
sw.Start();
try
{
// Start downloading the file
webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);
// Change the currently running executable so it can be overwritten.
Process thisprocess = Process.GetCurrentProcess();
string me = thisprocess.MainModule.FileName;
string bak = me + ".bak";
if (File.Exists(bak))
{
File.Delete(bak);
}
File.Move(me, bak);
File.Copy(bak, me);
//unzip
using (ZipFile zip = ZipFile.Read(file))
{
foreach (ZipEntry zipFiles in zip)
{
zipFiles.Extract(Root + "\\", true);
}
}
//download new version file
webClient.DownloadFile(Server + "pversion.txt", #Root + "pversion");
//Delete Zip File
deleteFile(file);
var spawn = Process.Start(me);
thisprocess.CloseMainWindow();
thisprocess.Close();
thisprocess.Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
And my problem is that once it finds a new version and starts downloading the file webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);, it instantly runs the code below which is the changing name, unzipping and downloading new version file progress
What I want it to do is wait for it to finish downloading the file, and THEN do the rest. How do I do this?
-- In case this is necessary, ProgressChanged:
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
label3.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")) + " " + string.Format("{0} MB's / {1} MB's", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));;
progressBar1.Value = e.ProgressPercentage;
label1.Text = e.ProgressPercentage.ToString() + "%";
}
and Completed:
private void Completed(object sender, AsyncCompletedEventArgs e)
{
sw.Reset();
if (e.Cancelled == true)
{
label1.Text = "Download cancelled!";
}
else
{
label1.Text = "Download completed!";
}
}
You can use the DownloadFile method. The Async word means that this method will run asynchronous (in other thread), that's why it's goes to next line praticaly instantly.
If you want wait for download ends, use the DownloadFile instead of DownloadFileAsync

c# WebClient DownloadProgresschanged TotalBytesToReceive = -1

I've had a look around the web and can't see anyone else with this problem. I'm using a web client using DownloadFileAsync and when the event handler (DownloadProgressChanged) is called the TotalBytesToReceive (from the DownloadProgressChangedArgs) is equalling -1 for some reason, thus stopping me from being able to use a progress bar. I'm detecting <0 and if so just guessing 100meg for now, to get round it.
The BytesRecieved is working however, and the file is actually being downloaded, and the AsynCompletedEventHadnler seems to be getting called so it knows its finished (so must know the TotalBytesToReceive somehow?).
I'm using a WebClient with credentials and proxy credentials to download from a password protected external site going through an internal network (so needed both) - not sure if that would make any difference.
I was previously using WebClient.DownloadData getting the byte data and saving it separately and putting it in a background worker,and it worked fine (if quite slow) but there was no way I could show progress this way. Also the DownloadFileAsync seems to do all of this for me so saved a lot of code.
private void DLFile_AsyncWithStatus(string DLlocation, string un, string pw, string destLoc)
{
WebClient wc = new WebClient();
wc.Credentials = new NetworkCredential(un, pw); // website login
wc.Proxy.Credentials = new NetworkCredential(ProxyUsername, ProxyPassword, ProxyDomain); //proxy login
Uri uri = new Uri(DLlocation);
// Specify that the DownloadFileCallback method gets called when the download completes.
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DLFile_AsynWithStatus_Completed);
// Specify a progress notification handler.
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressCallback);
try
{
wc.DownloadFileAsync(uri, destLoc);
}
catch (WebException e)
{
MessageBox.Show(e.Message);
}
}
private void DownloadProgressCallback(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
if (totalBytes < 0) {
totalBytes = 100.0 * 1000000.0; //guess 100 meg since it is not detecting total bytes
}
double percentage = bytesIn / totalBytes * 100;
lblTmpStatus.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
void DLFile_AsynWithStatus_Completed(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
Msg(e.Error.Message);
}
else
{
progressBar1.Value = 100;//temp.. finish it off incase was less than 100 meg.
}
}

c# Unable to download file ( file used by another process )

I have the main app and an updater. I start the updater from the main program and right after the updater started, i kill the main program. All ok by now.
Now, i check a xml file from a website for files that must be updated.
I use this to download the files:
Stopwatch sw = new Stopwatch();
public void DownloadFile(string urlAddress, string location)
{
using (WebClient webClient = new WebClient())
{
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
Uri URL = urlAddress.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ? new Uri(urlAddress) : new Uri("http://" + urlAddress);
sw.Start();
try
{
webClient.DownloadFileAsync(URL, location);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
labelSpeed.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));
progressBar.Value = e.ProgressPercentage;
labelPerc.Text = e.ProgressPercentage.ToString() + "%";
downloaded.Text = string.Format("{0} MB's / {1} MB's",
(e.BytesReceived / 1024d / 1024d).ToString("0.00"),
(e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
}
private void Completed(object sender, AsyncCompletedEventArgs e)
{
sw.Reset();
if (e.Error != null)
{
MessageBox.Show(e.Error.InnerException.Message,e.Error.Message);
}
if (e.Cancelled == true)
{
MessageBox.Show("Download has been canceled.");
}
else
{
MessageBox.Show("Download completed!");
}
}
And i call the download method using:
foreach (string file in dld)
{
DownloadFile(file, AppDomain.CurrentDomain.BaseDirectory+file);
MessageBox.Show("done with:" + file);
}
where, dld is List<string> dld = new List<string>();
When i call the download method, i get this error:
"An exception occured during a WebClient request.
The process cannot access the file xxx because it is used by another process."
PS: The updater is launched with admin rights.
I really do not understand what is the problem with the code. I've already asked here for the same problem, but it was only for one file(solved it with admin rights). Now i have multiple files to download and it doesn't work , even if the program is started with admin rights. I double checked, and the main program is closed.
Appreciate any help.
LATER EDIT : I think i found the problem. I have somewhere
Assembly assembly = Assembly.LoadFrom(path);
Version ver = assembly.GetName().Version; and i think this command locks the file.
Now i have to find out how to load and unload assembly. Back to google.
LAST EDIT : Found the solution and it works.
AssemblyName assembly = AssemblyName.GetAssemblyName(path);
Version ver = assembly.Version;
Try to use ProcMon (http://technet.microsoft.com/en-au/sysinternals/bb896645.aspx) and turn on the file monitoring and you can see what process is locking your file
Is it happening to all the files under that directory or a specific file only?

Downloading multiple files one at a time

This is the Code Below....
using System.Net;
//Create Temporary Folder to Holde All the Downloads............
namespace downloadFileCSharp10
{
public partial class Form1 : Form
{
string url = "URL";
string path = #"c:\Folder";
public Form1()
{
InitializeComponent();
}
void InitiateDownload(string RemoteAddress, string LocalFile, AsyncCompletedEventHandler CompleteCallBack, object userToken)
{
WebClient wc = new WebClient();
wc.DownloadProgressChanged += wc_DownloadProgressChanged;
wc.DownloadFileCompleted += wc_DownloadFileCompleted;
wc.DownloadFileAsync(new Uri(RemoteAddress), LocalFile, userToken);
}
void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
lblInfo1.Visible = true;
lblInfo1.ForeColor = Color.Red;
lblInfo1.Text = "Error Downloading ";
//throw e.Error;
}
else if (e.Cancelled)
{
lblInfo1.Visible = true;
lblInfo1.ForeColor = Color.Red;
lblInfo1.Text = "Download Cancelled " + e.UserState + e.Error;
}
else
{
lblInfo1.Visible = true;
lblInfo1.ForeColor = Color.Red;
lblInfo1.Text = e.UserState + " Download Complete!! ";
}
//throw new NotImplementedException();
}
void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
label1.Text = e.ProgressPercentage.ToString() + "%";
//throw new NotImplementedException();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnGetDownload_Click(object sender, EventArgs e)
{
//First Download
InitiateDownload(URL, path + "name you give.txt", wc_DownloadFileCompleted, "name you give.txt");
//Second Download
InitiateDownload(URL, path + "name you give2.txt", wc_DownloadFileCompleted, "name you give2.txt");
}
}
}
When I download multiple files it downloads all at the same time and from time to time I get one or two downloads that become corrupted. Also when I have more than 10 or 15 my application freezes a bit because its downloading all at the same. I want to be able to download at at least one or two at a time. I have looked around in using async and await but had no luck with. In addition I want to put a progressbar for each download file. So basically a loop but inserted into a listview but do not know how to go about it or maybe how to approach it.
Can you check http://blogs.msdn.com/b/spike/archive/2013/06/12/how-to-download-multiple-files-concurrently-using-webclient-and-the-downloadfileasync-method.aspx.
As I understand you should configure simultaneous outgoing connection limit to a higher number.
In the App.config file for the project, add the maxconnection setting:
<?xmlversion="1.0"encoding="utf-8" ?>
<configuration>
<system.net>
<connectionManagement>
<addaddress = "*"maxconnection = "10" />
</connectionManagement>
</system.net>
</configuration>
Credits to upper link. But this can only explain freezes when large number of files requested. For file corruption I think another point needs to be solved.

Categories

Resources