Beispiel #1
0
 //// Here we will abort the download if it takes more than 30 seconds to connect, because
 //// the Timeout property is ignored when using the asynchronous BeginGetResponse.
 private void TimeoutCallback(object State, bool TimedOut)
 {
     if (TimedOut)
     {
         HttpWebRequestState RequestState = (HttpWebRequestState)State;
         if (RequestState != null)
         {
             RequestState.Request.Abort();
         }
     }
 }
Beispiel #2
0
        //// Start the asynchronous download.
        public void DowloadFileAsync(string URL, string LocalFilePath, object userToken)
        {
            HttpWebRequest Request = default(HttpWebRequest);
            Uri            fileURI = new Uri(URL);  //// Will throw exception if empty or random string.

            //// Make sure it's a valid http:// or https:// url.
            if (fileURI.Scheme != Uri.UriSchemeHttp && fileURI.Scheme != Uri.UriSchemeHttps)
            {
                throw (new Exception("Invalid URL. Must be http:// or https://"));
            }



            //// Save this to private variables in case we need to resume.
            _URL           = URL;
            _LocalFilePath = LocalFilePath;
            _userToken     = userToken;

            //// Create the request.
            Request                   = (HttpWebRequest)(HttpWebRequest.Create(new Uri(URL)));
            Request.Credentials       = Credentials;
            Request.AllowAutoRedirect = true;
            Request.ReadWriteTimeout  = 30000;
            Request.Proxy             = Proxy;
            Request.KeepAlive         = false;
            Request.Headers           = Headers;   //// NOTE: Will throw exception if wrong headers supplied.

            //// If we're resuming, then add the AddRange header.
            if (_ResumeAsync)
            {
                FileInfo FileInfo = new FileInfo(LocalFilePath);
                if (FileInfo.Exists)
                {
                    Request.AddRange(Convert.ToInt32(FileInfo.Length));
                }
            }

            //// Signal we're busy downloading
            _isbusy = true;

            //// Make sure this is set to False or the download will stop immediately.
            _CancelAsync = false;

            //// This is the data we're sending to the GetResponse Callback.
            HttpWebRequestState State = new HttpWebRequestState(LocalFilePath, Request, _ResumeAsync, userToken);

            //// Begin to get a response from the server.
            IAsyncResult result = Request.BeginGetResponse(GetResponse_Callback, State);

            //// Add custom 30 second timeout for connecting.
            //// The Timeout property is ignored when using the asynchronous BeginGetResponse.
            ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), State, 30000, true);
        }
Beispiel #3
0
        //// Here we receive the response from the server. We do not check for the "Accept-Ranges"
        //// response header, in order to find out if the server supports resuming, because it MAY
        //// send the "Accept-Ranges" response header, but is not required to do so. This is
        //// unreliable, so we'll just continue and catch the exception that will occur if not
        //// supported and send it the DownloadCompleted event. We also don't check if the
        //// Content-Length is '-1', because some servers return '-1', eventhough the file/webpage
        //// you're trying to download is valid. e.ProgressPercentage returns '-1' in that case.
        private void GetResponse_Callback(IAsyncResult result)
        {
            HttpWebRequestState State             = (HttpWebRequestState)result.AsyncState;
            FileStream          DestinationStream = null;
            HttpWebResponse     Response          = null;
            Stopwatch           Duration          = new Stopwatch();

            byte[] Buffer                   = new byte[8192];
            int    BytesRead                = 0;
            int    ElapsedSeconds           = 0;
            int    DownloadSpeed            = 0;
            int    DownloadProgress         = 0;
            int    BytesReceivedThisSession = 0;

            try
            {
                //'// Get response
                Response = (HttpWebResponse)(State.Request.EndGetResponse(result));

                //// Asign Response headers to ReadOnly ResponseHeaders property.
                _ResponseHeaders = Response.Headers;

                //// If the server does not reply with an 'OK (200)' message when starting
                //// the download or a 'PartialContent (206)' message when resuming.
                if ((int)Response.StatusCode != System.Convert.ToInt32(HttpStatusCode.OK) & (int)Response.StatusCode != System.Convert.ToInt32(HttpStatusCode.PartialContent))
                {
                    //// Send error message to anyone who is listening.
                    OnDownloadCompleted(new FileDownloadCompletedEventArgs(new Exception(Response.StatusCode.ToString()), false, State.userToken));
                    return;
                }

                //// Create/open the file to write to.
                if (State.ResumeDownload)
                {
                    //// If resumed, then create or open the file.
                    DestinationStream = new FileStream(State.LocalFilePath, FileMode.OpenOrCreate, FileAccess.Write);
                }
                else
                {
                    //// If not resumed, then create the file, which will delete the existing file if it already exists.
                    DestinationStream = new FileStream(State.LocalFilePath, FileMode.Create, FileAccess.Write);
                    //// Get the ContentLength only when we're starting the download. Not when resuming.
                    _ContentLenght = Response.ContentLength;
                }

                //// Moves stream position to beginning of the file when starting the download.
                //// Moves stream position to end of the file when resuming the download.
                DestinationStream.Seek(0, SeekOrigin.End);

                //// Start timer to get download duration / download speed, etc.
                Duration.Start();

                //// Get the Response Stream.
                using (Stream responseStream = Response.GetResponseStream())
                {
                    do
                    {
                        //// Read some bytes.
                        BytesRead = responseStream.Read(Buffer, 0, Buffer.Length);
                        if (BytesRead > 0)
                        {
                            //// Write incoming data to the file.
                            DestinationStream.Write(Buffer, 0, BytesRead);
                            //// Count the total number of bytes downloaded.
                            _TotalBytesReceived += BytesRead;
                            //// Count the number of bytes downloaded this session (Resume).
                            BytesReceivedThisSession += BytesRead;
                            //// Get number of elapsed seconds (need round number to prevent 'division by zero' error).
                            ElapsedSeconds = System.Convert.ToInt32(Duration.Elapsed.TotalSeconds);

                            //// Update frequency: No Delay, every Half a Second or every Second.
                            if (ProgressUpdateFrequency == UpdateFrequency.NoDelay)
                            {
                                //// Calculate download speed in bytes per second.
                                if (ElapsedSeconds > 0)
                                {
                                    DownloadSpeed = BytesReceivedThisSession / ElapsedSeconds;
                                }
                                //// Send download progress to anyone who is listening.
                                OnDownloadProgressChanged(new FileDownloadProgressChangedEventArgs(_TotalBytesReceived, (int)_ContentLenght, ElapsedSeconds, DownloadSpeed, State.userToken));
                            }
                            else if (ProgressUpdateFrequency == UpdateFrequency.HalfSecond)
                            {
                                if (System.Convert.ToInt32(Duration.ElapsedMilliseconds - DownloadProgress) >= 500)
                                {
                                    DownloadProgress = (int)Duration.ElapsedMilliseconds;
                                    //// Calculate download speed in bytes per second.
                                    if (ElapsedSeconds > 0)
                                    {
                                        DownloadSpeed = BytesReceivedThisSession / ElapsedSeconds;
                                    }
                                    //// Send download progress to anyone who is listening.
                                    OnDownloadProgressChanged(new FileDownloadProgressChangedEventArgs(_TotalBytesReceived, (int)_ContentLenght, ElapsedSeconds, DownloadSpeed, State.userToken));
                                }
                            }
                            else if (ProgressUpdateFrequency == UpdateFrequency.Second)
                            {
                                if (System.Convert.ToInt32(Duration.ElapsedMilliseconds - DownloadProgress) >= 1000)
                                {
                                    DownloadProgress = (int)Duration.ElapsedMilliseconds;
                                    //// Calculate download speed in bytes per second.
                                    if (ElapsedSeconds > 0)
                                    {
                                        DownloadSpeed = BytesReceivedThisSession / ElapsedSeconds;
                                    }
                                    //// Send download progress to anyone who is listening.
                                    OnDownloadProgressChanged(new FileDownloadProgressChangedEventArgs(_TotalBytesReceived, (int)_ContentLenght, ElapsedSeconds, DownloadSpeed, State.userToken));
                                }
                            }

                            //// Exit loop when paused.
                            if (_CancelAsync)
                            {
                                break;
                            }
                        }
                    } while (!(BytesRead == 0));
                }


                //// Send download progress once more. If the UpdateFrequency has been set to
                //// HalfSecond or Second, then the last percentage returned might be 98% or 99%.
                //// This makes sure it's 100%.
                OnDownloadProgressChanged(new FileDownloadProgressChangedEventArgs(_TotalBytesReceived, (int)_ContentLenght, System.Convert.ToInt32(Duration.Elapsed.TotalSeconds), DownloadSpeed, State.userToken));

                if (_CancelAsync)
                {
                    //// Send completed message (Paused) to anyone who is listening.
                    OnDownloadCompleted(new FileDownloadCompletedEventArgs(null, true, State.userToken));
                }
                else
                {
                    //// Send completed message (Finished) to anyone who is listening.
                    OnDownloadCompleted(new FileDownloadCompletedEventArgs(null, false, State.userToken));
                }
            }
            catch (Exception ex)
            {
                //// Send completed message (Error) to anyone who is listening.
                OnDownloadCompleted(new FileDownloadCompletedEventArgs(ex, false, State.userToken));
            }
            finally
            {
                //// Close the file.
                if (DestinationStream != null)
                {
                    DestinationStream.Flush();
                    DestinationStream.Close();
                    DestinationStream = null;
                }
                //// Stop and reset the duration timer.
                Duration.Reset();
                Duration = null;
                //// Signal we're not downloading anymore.
                _isbusy = false;
            }
        }