Recently updated a download gadget that mainly improves the following points:
1. In some branches of the local area network, not connected to the external network
2. Files that are downloaded or updated before they are updated on the server
3. No download Progress tips
4. Cannot terminate the download
Here are some tips to share with you.
In view of the complex network environment, I decided to use different programming interfaces to download the experiment to increase the usability of the program.
Here are just a few ways to use WebClient, and a follow-up article will describe other methods. The main ideas and key codes are presented in the blog post, and the complete demo is attached to the end of the article.
using a proxy to access the network
Many of the company's employees are through the company set up agents online. Through the agent to the Internet is mainly to facilitate the company to carry out a variety of control, of course, can also achieve a number of special functions ... However, this will bring some problems to our Program Access network.
In fact, the API in WebClient is already very smart, such as the HttpWebRequest object we created, which comes with a Proxy property. In other words, Webhttprequest uses the proxy found by default. It's great, and it can handle a lot of things. However, if the default proxy needs to authenticate the identity of the domain user, accessing the network using webhttprequest may fail. View Proxy at this time. The Credentials property, which finds it to be null.
From the WebClient API you can take the system default Credentials, but it is not clear why the Proxy.credentials property is not set to this value by default. We can set it up for ourselves.
Request. Proxy.credentials = CredentialCache.DefaultCredentials;
However, the actual network environment may be more complex, requiring users to designate a networked agent, and also specify the Credentials required for networking. The wording is as follows:
Newnew networkcredential (Proxyusername, PROXYUSERPASSWD, DomainName);
Overcoming Caching
The cache is everywhere, the server-side CDN will have the cache, and the client's proxy layer will have a cache. So often the problem is: The file on the server is clearly updated, or there will be some customers downloaded to the old file. Let's deal with the client caching problem first.
The Cachepolicy.level property of HttpWebRequest is to set the cache policy, except that its default value is Bypasscache. We can change it to Reload:
New System.Net.Cache.RequestCachePolicy (System.Net.Cache.RequestCacheLevel.Reload);
Next is the server-side caching problem.
Now everyone seems to be using CDN, you can often find the CDN side of the cache update problems. There is no good solution for checking online, but there is a good workaround to add a random string as a parameter in the request.
New Random (); string s ="? " + S;
It is important to note that for caching, you must use a policy that conforms to the current use case and is not fits.
a more friendly download process
Use the scroll bar to show download progress, show real-time download speed, and allow users to cancel the download:
Here is the core code of the download, we divide it into the calculation of download percentage and calculate the current download speed are described separately.
//get the length of the downloaded fileDoubleContentLength =downloadmanager.getcontentlength (myhttpwebclient);byte[] buffer =New byte[buffersize];LongDownloadedlength =0;LongCurrenttimespandatalength =0; intcurrentdatalength; while((Currentdatalength = stream.) Read (Buffer,0, buffersize)) >0&&! This. _canceldownload) {filestream.write (buffer,0, currentdatalength); Downloadedlength+= (Long) Currentdatalength; Currenttimespandatalength+= (Long) Currentdatalength; intIntdownloadspeed =0; if( This. _downloadstopwatch.elapsedmilliseconds > -) { DoubleNUM5 = (Double) Currenttimespandatalength/1024.0; DoubleNUM6 = (Double) This. _downloadstopwatch.elapsedmilliseconds/1000.0; DoubleDoubledownloadspeed = NUM5/NUM6; Intdownloadspeed= (int) Math.Round (Doubledownloadspeed,0); This. _downloadstopwatch.reset (); This. _downloadstopwatch.start (); Currenttimespandatalength=0; } DoubleDoubledownloadpersent =0.0; if(ContentLength >0.0) {doubledownloadpersent= (Double) Downloadedlength/ContentLength; }}
calculate download percentage during download
You first need to get the length of the file to download from the HTTP request, please refer to the demo in this article for details.
double contentlength = Downloadmanager.getcontentlength (myhttpwebclient);
Every time the data is read from the file stream, we know how many bytes are read (currentdatalength) and the length of the file that is currently downloaded is accumulated.
Downloadedlength + = (long) currentdatalength;
Then do a division on the line:
Doubledownloadpersent = (double) downloadedlength/contentlength;
Calculate real-time download speed
For the current download speed, we calculate the number of bytes downloaded in the past over a period of time. The time period can be obtained using StopWatch, and the time period I select requires more than 800 milliseconds.
if( This. _downloadstopwatch.elapsedmilliseconds > -){ /***********************************/ //Calculate download speed over the previous time period DoubleNUM5 = (Double) Currenttimespandatalength/1024.0; DoubleNUM6 = (Double) This. _downloadstopwatch.elapsedmilliseconds/1000.0; DoubleDoubledownloadspeed = NUM5/NUM6; /***********************************/Intdownloadspeed= (int) Math.Round (Doubledownloadspeed,0); //Reset the time timer and the data counter after the speed calculation is completed, and start the next calculation This. _downloadstopwatch.reset (); This. _downloadstopwatch.start (); Currenttimespandatalength=0;}
In fact, each time the download speed period is ignored, but this does not affect the calculation results, I just want to ensure that the distance last calculated more than 800 milliseconds on the line.
allow user to cancel download
For a task with a long execution time, the user is not allowed to cancel it is hated! Especially when the internet is not very good. So we need to give the user a choice: to end the current journey with pleasure (not pain).
And all this is so easy for us!
while 0 0 &&! this. _canceldownload) {}
When reading data from the data stream, we check that the user has pressed the "Cancel" button, which is the this._canceldownload variable here. If it is true, the current download ends.
At this point, the user complained most of the points are taken care of. In fact, there's not much code added, and every point of knowledge looks so subtle. But it obviously improves the user experience. This also gives us some inspiration, the completion of the main function may only be part of the work, and some other work may not be so obvious, we need to constantly experience, found that ...
Demo Download
C # File Download: WebClient