Reputation: 81801
I am testing some features of WebClient
class and I decided to see how DownloadProgressChanged
works so I made up such code:
static void Main(string[] args)
{
WebClient client = new WebClient();
client.Proxy = null;
client.BaseAddress = "ftp://ftp.xxxxxxx.com";
CredentialCache cache = new CredentialCache();
NetworkCredential credential = new NetworkCredential("userxxx", "passxxxx");
client.Credentials = credential;
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
Uri remoteFile;
Uri.TryCreate("/public_html/folderxxxx/Pictures/Product/Resized/1.jpg", System.UriKind.Relative, out remoteFile);
client.DownloadFileAsync(remoteFile, "1.jpg");
System.Diagnostics.Process.Start("1.jpg");
Console.ReadLine();
}
static void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
Console.WriteLine(e.ProgressPercentage.ToString());
}
When I run this application, this is what I see as progress:
Looks nothing fancy. Ben Albahari suggest using new Thread instead of using Async method and this event handler is useful when you actually use Async method.
So how can I show Progress truly?
EDIT:
According to MSDN this should be done:
A passive FTP file transfer will always show a progress percentage of zero, since the server did not send the file size. To show progress, you can change the FTP connection to active by overriding the GetWebRequest virtual method:
Sample Code:
internal class MyWebClient:WebClient{
protected override WebRequest GetWebRequest(Uri address) {
FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address);
req.UsePassive = false;
return req;
}
}
Which is what I did but the same problem happens:
Upvotes: 2
Views: 9264
Reputation: 2246
There seem to be a lot of people asking this question.
So far as I can tell your server will only report back progress if it is set you allow active connections. It looks like PASV (passive FTP) can be enabled or disabled on the server. And the mode used should be determined by what the server is set to use and what is between server and client.
EDIT: I enabled System.Net.Tracing on my project and tried both passive and active modes and not only do both work as expected... TotalBytes is still -1 so my thinking is the note on MSDN
http://msdn.microsoft.com/en-US/library/system.net.webclient.downloadprogresschanged(v=vs.80).aspx
is mistaken or we are missing something.
http://compnetworking.about.com/cs/protocolsftp/g/bldef_pasv.htm
http://slacksite.com/other/ftp.html
http://fetchsoftworks.com/fetch/help/Contents/Concepts/ActiveAndPassive.html
So overriding the WebRequest method will make no difference if the server does not use active connections.
However... as you can see from your own command line readout it does report back the BytesReceived correctly.
Find out the file size and you're away...
I expect there is a more efficient method but... I used an FtpWebRequest to get the file size before downloading and then run DownloadFileAsync and pass the file size to the DownloadProgressCallback using:
Client.DownloadProgressChanges += (sender, e) => DownloadProgressCallback( fileSize, e)
Hope this helps :)
Upvotes: 1
Reputation: 33738
Did you read the documentation??
A passive FTP file transfer will always show a progress percentage of zero, since the server did not send the file size. To show progress, you can change the FTP connection to active by overriding the GetWebRequest virtual method:
internal class MyWebClient:WebClient{
protected override WebRequest GetWebRequest(Uri address) {
FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address);
req.UsePassive = false;
return req;
}
}
Upvotes: 1