Beispiel #1
0
        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            // validate input
            if (urlList == null || urlList.Count == 0)
            {
                if (string.IsNullOrEmpty(url))
                {
                    //no sites specified, bail out
                    if (!bw.CancellationPending)
                    {
                        bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, new Exception("No download URLs are specified.") });
                    }

                    return;
                }

                //single site specified, add it to the list
                urlList = new List <string> {
                    url
                };
            }

            // use the custom proxy if provided
            if (CustomProxy != null)
            {
                WebRequest.DefaultWebProxy = CustomProxy;
            }
            else
            {
                IWebProxy proxy = WebRequest.GetSystemWebProxy();

                if (proxy.Credentials == null)
                {
                    proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
                }

                WebRequest.DefaultWebProxy = proxy;
            }

            if (DownloadAll)
            {
                totalDownloadSize    = 0;
                totalBytesDownloaded = 0;

                foreach (string s in urlList)
                {
                    long size = DownloadData.GetFileSize(s);
                    if (size > -1)
                    {
                        totalDownloadSize += size;
                    }
                }
            }
            else
            {
                totalDownloadSize = -1;
            }

            // try each url in the list until one succeeds
            bool      allFailedWaitingForResponse = true;
            Exception ex = null;

            foreach (string s in urlList)
            {
                CurrentURLIndex = urlList.IndexOf(s);

                ex = null;
                try
                {
                    url = s;
                    BeginDownload();
                    ValidateDownload();
                }
                catch (Exception except)
                {
                    ex = except;

                    if (!waitingForResponse)
                    {
                        allFailedWaitingForResponse = false;
                    }
                }

                // If we got through that without an exception, we found a good url
                if (!DownloadAll && (ex == null || bw.CancellationPending))
                {
                    allFailedWaitingForResponse = false;
                    break;
                }
            }


            /*
             * If all the sites failed before a response was received then either the
             * internet connection is shot, or the Proxy is shot. Either way it can't
             * hurt to try downloading without the proxy:
             */
            if (allFailedWaitingForResponse && WebRequest.DefaultWebProxy != null)
            {
                // try the sites again without a proxy
                WebRequest.DefaultWebProxy = null;

                foreach (string s in urlList)
                {
                    ex = null;
                    try
                    {
                        url = s;
                        BeginDownload();
                        ValidateDownload();
                    }
                    catch (Exception except)
                    {
                        ex = except;
                    }

                    // If we got through that without an exception, we found a good url
                    if (ex == null || bw.CancellationPending)
                    {
                        break;
                    }
                }
            }

            // Process complete (either successfully or failed), report back
            if (bw.CancellationPending || ex != null)
            {
                bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, ex });
            }
            else
            {
                bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null });
            }
        }
Beispiel #2
0
        // Begin downloading the file at the specified url, and save it to the given folder.
        void BeginDownload()
        {
            DownloadData data = null;
            FileStream   fs   = null;

            try
            {
                //start the stopwatch for speed calc
                sw.Start();

                // get download details
                waitingForResponse = true;
                data = DownloadData.Create(url, destFolder);
                waitingForResponse = false;

                //reset the adler
                downloadedAdler32.Reset();

                DownloadingTo = data.Filename;

                if (!File.Exists(DownloadingTo))
                {
                    // create the file
                    fs = File.Open(DownloadingTo, FileMode.Create, FileAccess.Write);
                }
                else
                {
                    // read in the existing data to calculate the adler32
                    if (Adler32 != 0)
                    {
                        GetAdler32(DownloadingTo);
                    }

                    // apend to an existing file (resume)
                    fs = File.Open(DownloadingTo, FileMode.Append, FileAccess.Write);
                }

                // create the download buffer
                byte[] buffer = new byte[BufferSize];

                int readCount;

                // update how many bytes have already been read
                sentSinceLastCalc = data.StartPoint; //for BPS calculation

                while ((readCount = data.DownloadStream.Read(buffer, 0, BufferSize)) > 0)
                {
                    // break on cancel
                    if (bw.CancellationPending)
                    {
                        data.Close();
                        fs.Close();
                        break;
                    }

                    // update total bytes read
                    data.StartPoint += readCount;
                    if (DownloadAll)
                    {
                        totalBytesDownloaded += readCount;
                    }

                    // update the adler32 value
                    if (Adler32 != 0)
                    {
                        downloadedAdler32.Update(buffer, 0, readCount);
                    }

                    // save block to end of file
                    fs.Write(buffer, 0, readCount);

                    //calculate download speed
                    if (DownloadAll)
                    {
                        calculateBps(totalBytesDownloaded, totalDownloadSize);
                    }
                    else
                    {
                        calculateBps(data.StartPoint, data.TotalDownloadSize);
                    }

                    // send progress info
                    if (!bw.CancellationPending)
                    {
                        if (DownloadAll)
                        {
                            int percentDone = (int)((totalBytesDownloaded * 100) / totalDownloadSize);
                            bw.ReportProgress(0, new object[] {
                                //use the realtive progress or the raw progress
                                UseRelativeProgress?
                                InstallUpdate.GetRelativeProgess(0, percentDone) :
                                    percentDone,

                                    // unweighted percent
                                    percentDone,
                                    downloadSpeed, ProgressStatus.None, null
                            });
                        }
                        else
                        {
                            bw.ReportProgress(0, new object[] {
                                //use the realtive progress or the raw progress
                                UseRelativeProgress?
                                InstallUpdate.GetRelativeProgess(0, data.PercentDone) :
                                    data.PercentDone,

                                    // unweighted percent
                                    data.PercentDone,
                                    downloadSpeed, ProgressStatus.None, null
                            });
                        }
                    }

                    // break on cancel
                    if (bw.CancellationPending)
                    {
                        data.Close();
                        fs.Close();
                        break;
                    }
                }
            }
            catch (UriFormatException e)
            {
                throw new Exception(string.Format("Could not parse the URL \"{0}\" - it's either malformed or is an unknown protocol.", url), e);
            }
            catch (Exception e)
            {
                if (string.IsNullOrEmpty(DownloadingTo))
                {
                    throw new Exception(string.Format("Error trying to save file: {0}\n\n{1}", e.Message, e.StackTrace), e);
                }
                else
                {
                    throw new Exception(string.Format("Error trying to save file \"{0}\": {1}", DownloadingTo, e.Message), e);
                }
            }
            finally
            {
                if (data != null)
                {
                    data.Close();
                }
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }
Beispiel #3
0
        public static DownloadData Create(string url, string destFolder)
        {
            DownloadData downloadData = new DownloadData();
            WebRequest   req          = GetRequest(url);

            try
            {
                if (req is FtpWebRequest)
                {
                    // get the file size for FTP files
                    req.Method            = WebRequestMethods.Ftp.GetFileSize;
                    downloadData.response = req.GetResponse();
                    downloadData.GetFileSize();

                    // new request for downloading the FTP file
                    req = GetRequest(url);
                    downloadData.response = req.GetResponse();
                }
                else
                {
                    downloadData.response = req.GetResponse();
                    downloadData.GetFileSize();
                }
            }
            catch (Exception e)
            {
                throw new Exception(string.Format("Error downloading \"{0}\": {1}", url, e.Message), e);
            }

            // Check to make sure the response isn't an error. If it is this method
            // will throw exceptions.
            ValidateResponse(downloadData.response, url);

            // Take the name of the file given to use from the web server.
            string fileName = downloadData.response.Headers["Content-Disposition"];

            if (fileName != null)
            {
                int fileLoc = fileName.IndexOf("filename=", StringComparison.OrdinalIgnoreCase);

                if (fileLoc != -1)
                {
                    // go past "filename="
                    fileLoc += 9;

                    if (fileName.Length > fileLoc)
                    {
                        // trim off an ending semicolon if it exists
                        int end = fileName.IndexOf(';', fileLoc);

                        if (end == -1)
                        {
                            end = fileName.Length - fileLoc;
                        }
                        else
                        {
                            end -= fileLoc;
                        }

                        fileName = fileName.Substring(fileLoc, end).Trim();
                    }
                    else
                    {
                        fileName = null;
                    }
                }
                else
                {
                    fileName = null;
                }
            }

            if (string.IsNullOrEmpty(fileName))
            {
                // brute force the filename from the url
                fileName = Path.GetFileName(downloadData.response.ResponseUri.LocalPath);
            }

            // trim out non-standard filename characters
            if (!string.IsNullOrEmpty(fileName) && fileName.IndexOfAny(invalidFilenameChars.ToArray()) != -1)
            {
                //make a new string builder (with at least one bad character)
                StringBuilder newText = new StringBuilder(fileName.Length - 1);

                //remove the bad characters
                for (int i = 0; i < fileName.Length; i++)
                {
                    if (invalidFilenameChars.IndexOf(fileName[i]) == -1)
                    {
                        newText.Append(fileName[i]);
                    }
                }

                fileName = newText.ToString().Trim();
            }

            // if filename *still* is null or empty, then generate some random temp filename
            if (string.IsNullOrEmpty(fileName))
            {
                fileName = Path.GetFileName(Path.GetTempFileName());
            }

            string downloadTo = Path.Combine(destFolder, fileName);

            downloadData.Filename = downloadTo;

            // If we don't know how big the file is supposed to be,
            // we can't resume, so delete what we already have if something is on disk already.
            if (!downloadData.IsProgressKnown && File.Exists(downloadTo))
            {
                File.Delete(downloadTo);
            }

            if (downloadData.IsProgressKnown && File.Exists(downloadTo))
            {
                // We only support resuming on http requests
                if (!(downloadData.Response is HttpWebResponse))
                {
                    File.Delete(downloadTo);
                }
                else
                {
                    // Try and start where the file on disk left off
                    downloadData.start = new FileInfo(downloadTo).Length;

                    // If we have a file that's bigger than what is online, then something
                    // strange happened. Delete it and start again.
                    if (downloadData.start > downloadData.size)
                    {
                        File.Delete(downloadTo);
                    }
                    else if (downloadData.start < downloadData.size)
                    {
                        // Try and resume by creating a new request with a new start position
                        downloadData.response.Close();
                        req = GetRequest(url);
                        ((HttpWebRequest)req).AddRange((int)downloadData.start);
                        downloadData.response = req.GetResponse();

                        if (((HttpWebResponse)downloadData.Response).StatusCode != HttpStatusCode.PartialContent)
                        {
                            // They didn't support our resume request.
                            File.Delete(downloadTo);
                            downloadData.start = 0;
                        }
                    }
                }
            }

            return(downloadData);
        }
Beispiel #4
0
        public static DownloadData Create(string url, string destFolder)
        {
            DownloadData downloadData = new DownloadData();
            WebRequest req = GetRequest(url);

            try
            {
                if (req is FtpWebRequest)
                {
                    // get the file size for FTP files
                    req.Method = WebRequestMethods.Ftp.GetFileSize;
                    downloadData.response = req.GetResponse();
                    downloadData.GetFileSize();

                    // new request for downloading the FTP file
                    req = GetRequest(url);
                    downloadData.response = req.GetResponse();
                }
                else
                {
                    downloadData.response = req.GetResponse();
                    downloadData.GetFileSize();
                }
            }
            catch (Exception e)
            {
                throw new Exception(string.Format("Error downloading \"{0}\": {1}", url, e.Message), e);
            }

            // Check to make sure the response isn't an error. If it is this method
            // will throw exceptions.
            ValidateResponse(downloadData.response, url);

            // Take the name of the file given to use from the web server.
            string fileName = downloadData.response.Headers["Content-Disposition"];

            if (fileName != null)
            {
                int fileLoc = fileName.IndexOf("filename=", StringComparison.OrdinalIgnoreCase);

                if (fileLoc != -1)
                {
                    // go past "filename="
                    fileLoc += 9;

                    if (fileName.Length > fileLoc)
                    {
                        // trim off an ending semicolon if it exists
                        int end = fileName.IndexOf(';', fileLoc);

                        if (end == -1)
                            end = fileName.Length - fileLoc;
                        else
                            end -= fileLoc;

                        fileName = fileName.Substring(fileLoc, end).Trim();
                    }
                    else
                        fileName = null;
                }
                else
                    fileName = null;
            }

            if (string.IsNullOrEmpty(fileName))
            {
                // brute force the filename from the url
                fileName = Path.GetFileName(downloadData.response.ResponseUri.LocalPath);
            }

            // trim out non-standard filename characters
            if (!string.IsNullOrEmpty(fileName) && fileName.IndexOfAny(invalidFilenameChars.ToArray()) != -1)
            {
                //make a new string builder (with at least one bad character)
                StringBuilder newText = new StringBuilder(fileName.Length - 1);

                //remove the bad characters
                for (int i = 0; i < fileName.Length; i++)
                {
                    if (invalidFilenameChars.IndexOf(fileName[i]) == -1)
                        newText.Append(fileName[i]);
                }

                fileName = newText.ToString().Trim();
            }

            // if filename *still* is null or empty, then generate some random temp filename
            if (string.IsNullOrEmpty(fileName))
                fileName = Path.GetFileName(Path.GetTempFileName());

            string downloadTo = Path.Combine(destFolder, fileName);

            downloadData.Filename = downloadTo;

            // If we don't know how big the file is supposed to be,
            // we can't resume, so delete what we already have if something is on disk already.
            if (!downloadData.IsProgressKnown && File.Exists(downloadTo))
                File.Delete(downloadTo);

            if (downloadData.IsProgressKnown && File.Exists(downloadTo))
            {
                // We only support resuming on http requests
                if (!(downloadData.Response is HttpWebResponse))
                {
                    File.Delete(downloadTo);
                }
                else
                {
                    // Try and start where the file on disk left off
                    downloadData.start = new FileInfo(downloadTo).Length;

                    // If we have a file that's bigger than what is online, then something
                    // strange happened. Delete it and start again.
                    if (downloadData.start > downloadData.size)
                        File.Delete(downloadTo);
                    else if (downloadData.start < downloadData.size)
                    {
                        // Try and resume by creating a new request with a new start position
                        downloadData.response.Close();
                        req = GetRequest(url);
                        ((HttpWebRequest)req).AddRange((int)downloadData.start);
                        downloadData.response = req.GetResponse();

                        if (((HttpWebResponse)downloadData.Response).StatusCode != HttpStatusCode.PartialContent)
                        {
                            // They didn't support our resume request.
                            File.Delete(downloadTo);
                            downloadData.start = 0;
                        }
                    }
                }
            }

            return downloadData;
        }