Download File with Update Progress in .Net

Next best thing to wget on Windows. 😉

VB

Imports System.Net
Imports System.IO

Namespace SoftwareAgent
    Public Class WebDownload
        Public Event FileDownloadProgressChanged(ByVal iNewProgress As Long)
        Public Event FileDownloadSizeObtained(ByVal iFileSize As Long)
        Public Event FileDownloadComplete()
        Public Event FileDownloadFailed(ByVal ex As Exception)

        Private mCurrentFile As String = ""
        Public ReadOnly Property FileName() As String
            Get
                Return mCurrentFile
            End Get
        End Property

        Public Sub New(ByVal URL As String)
            Dim wRemote As System.Net.WebRequest
            wRemote = System.Net.WebRequest.Create(URL)
            Dim HeaderDataCollection As System.Net.WebHeaderCollection = wRemote.GetResponse.Headers
            If Not HeaderDataCollection("Content-Disposition") Is Nothing Then
                mCurrentFile = HeaderDataCollection("Content-Disposition").Split("=")(1)
            Else
                If URL.IndexOf("/"c) = -1 Then : mCurrentFile = ""
                Else : mCurrentFile = "\" & URL.Substring(URL.LastIndexOf("/"c) + 1) : End If
            End If
        End Sub

        Public Function DownloadFile(ByVal URL As String, ByVal Location As String) As Boolean
            Try
                Dim WC As New WebClient
                WC.DownloadFile(URL, Location)
                RaiseEvent FileDownloadComplete()
                Return True
            Catch ex As Exception
                RaiseEvent FileDownloadFailed(ex)
                Return False
            End Try
        End Function

        Private Function GetFileName(ByVal URL As String) As String
            Try
                Return URL.Substring(URL.LastIndexOf("/") + 1)
            Catch ex As Exception
                Return URL
            End Try
        End Function

        'TODO: consolidate with download file and remove URL required param change to constructor
        Public Function DownloadFileWithProgress(ByVal URL As String, ByVal Location As String) As Boolean
            Dim FS As FileStream
            Try
                Dim wRemote As WebRequest
                Dim bBuffer As Byte()
                ReDim bBuffer(256)
                Dim iBytesRead As Integer
                Dim iTotalBytesRead As Integer

                FS = New FileStream(Location, FileMode.Create, FileAccess.Write)
                wRemote = WebRequest.Create(URL)
                Dim myWebResponse As WebResponse = wRemote.GetResponse

                RaiseEvent FileDownloadSizeObtained(myWebResponse.ContentLength)
                Dim sChunks As Stream = myWebResponse.GetResponseStream
                Do
                    iBytesRead = sChunks.Read(bBuffer, 0, 256)
                    FS.Write(bBuffer, 0, iBytesRead)
                    iTotalBytesRead += iBytesRead
                    If myWebResponse.ContentLength < iTotalBytesRead Then
                        RaiseEvent FileDownloadProgressChanged(myWebResponse.ContentLength)
                    Else
                        RaiseEvent FileDownloadProgressChanged(iTotalBytesRead)
                    End If
                Loop While Not iBytesRead = 0
                sChunks.Close()
                FS.Close()
                RaiseEvent FileDownloadComplete()
                Return True
            Catch ex As Exception
                If Not (FS Is Nothing) Then
                    FS.Close()
                    FS = Nothing
                End If
                RaiseEvent FileDownloadFailed(ex)
                Return False
            End Try
        End Function

        Public Shared Function FormatFileSize(ByVal Size As Long) As String
            Try
                Dim KB As Integer = 1024
                Dim MB As Integer = KB * KB
                ' Return size of file in kilobytes.
                If Size < KB Then
                    Return (Size.ToString("D") & " bytes")
                Else
                    Select Case Size / KB
                        Case Is < 1000
                            Return (Size / KB).ToString("N") & "KB"
                        Case Is < 1000000
                            Return (Size / MB).ToString("N") & "MB"
                        Case Is < 10000000
                            Return (Size / MB / KB).ToString("N") & "GB"
                    End Select
                End If
            Catch ex As Exception
                Return Size.ToString
            End Try
        End Function
    End Class
End Namespace

C# (note this is autoconversion and actual project is in VB):

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Net;
using System.IO;

	public class WebDownload
	{
		public event FileDownloadProgressChangedEventHandler FileDownloadProgressChanged;
		public delegate void FileDownloadProgressChangedEventHandler(long iNewProgress);
		public event FileDownloadSizeObtainedEventHandler FileDownloadSizeObtained;
		public delegate void FileDownloadSizeObtainedEventHandler(long iFileSize);
		public event FileDownloadCompleteEventHandler FileDownloadComplete;
		public delegate void FileDownloadCompleteEventHandler();
		public event FileDownloadFailedEventHandler FileDownloadFailed;
		public delegate void FileDownloadFailedEventHandler(Exception ex);

		private string mCurrentFile = "";
		public string FileName {
			get { return mCurrentFile; }
		}

		public WebDownload(string URL)
		{
			System.Net.WebRequest wRemote = null;
			wRemote = System.Net.WebRequest.Create(URL);
			System.Net.WebHeaderCollection HeaderDataCollection = wRemote.GetResponse().Headers;
			if ((HeaderDataCollection["Content-Disposition"] != null)) {
				mCurrentFile = HeaderDataCollection["Content-Disposition"].Split("=")[1];
			} else {
				if (URL.IndexOf('/') == -1) {
					mCurrentFile = "";
				} else {
					mCurrentFile = "\\" + URL.Substring(URL.LastIndexOf('/') + 1);
				}
			}
		}

		public bool DownloadFile(string URL, string Location)
		{
			try {
				WebClient WC = new WebClient();
				WC.DownloadFile(URL, Location);
				if (FileDownloadComplete != null) {
					FileDownloadComplete();
				}
				return true;
			} catch (Exception ex) {
				if (FileDownloadFailed != null) {
					FileDownloadFailed(ex);
				}
				return false;
			}
		}

		private string GetFileName(string URL)
		{
			try {
				return URL.Substring(URL.LastIndexOf("/") + 1);
			} catch (Exception ex) {
				return URL;
			}
		}

		//TODO: consolidate with download file and remove URL required param change to constructor
		public bool DownloadFileWithProgress(string URL, string Location)
		{
			FileStream FS = null;
			try {
				WebRequest wRemote = null;
				byte[] bBuffer = null;
				bBuffer = new byte[257];
				int iBytesRead = 0;
				int iTotalBytesRead = 0;

				FS = new FileStream(Location, FileMode.Create, FileAccess.Write);
				wRemote = WebRequest.Create(URL);
				WebResponse myWebResponse = wRemote.GetResponse();

				if (FileDownloadSizeObtained != null) {
					FileDownloadSizeObtained(myWebResponse.ContentLength);
				}
				Stream sChunks = myWebResponse.GetResponseStream();
				do {
					iBytesRead = sChunks.Read(bBuffer, 0, 256);
					FS.Write(bBuffer, 0, iBytesRead);
					iTotalBytesRead += iBytesRead;
					if (myWebResponse.ContentLength < iTotalBytesRead) {
						if (FileDownloadProgressChanged != null) {
							FileDownloadProgressChanged(myWebResponse.ContentLength);
						}
					} else {
						if (FileDownloadProgressChanged != null) {
							FileDownloadProgressChanged(iTotalBytesRead);
						}
					}
				} while (!(iBytesRead == 0));
				sChunks.Close();
				FS.Close();
				if (FileDownloadComplete != null) {
					FileDownloadComplete();
				}
				return true;
			} catch (Exception ex) {
				if ((FS != null)) {
					FS.Close();
					FS = null;
				}
				if (FileDownloadFailed != null) {
					FileDownloadFailed(ex);
				}
				return false;
			}
		}

		public static string FormatFileSize(long Size)
		{
			try {
				int KB = 1024;
				int MB = KB * KB;
				// Return size of file in kilobytes.
				if (Size < KB) {
					return (Size.ToString("D") + " bytes");
				} else {
					switch (Size / KB) {
						case  // ERROR: Case labels with binary operators are unsupported : LessThan
1000:
							return (Size / KB).ToString("N") + "KB";
						case  // ERROR: Case labels with binary operators are unsupported : LessThan
1000000:
							return (Size / MB).ToString("N") + "MB";
						case  // ERROR: Case labels with binary operators are unsupported : LessThan
10000000:
							return (Size / MB / KB).ToString("N") + "GB";
					}
				}
			} catch (Exception ex) {
				return Size.ToString();
			}
		}
	}

Advertisement

About Ronnie Diaz

Ronnie Diaz is a software engineer and tech consultant. Ronnie started his career in front-end and back-end development for companies in ecommerce, service industries and remote education. This work transitioned from traditional desktop client-server applications through early cloud development. Software included human resource management and service technician workflows, online retail e-commerce and electronic ordering and fulfillment, IVR customer relational systems, and video streaming remote learning SCORM web applications. Hands on server experience and software performance optimization led to creation of a startup business focused on collocated data center services and continued experience with video streaming hardware and software. This led to a career in Amazon Prime Video where Ronnie is currently employed, building software and systems which stream live sports and events for millions of viewers around the world.

Posted on May 4, 2011, in Programming & Development and tagged , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: