How to Upload a Folder Recursive to FTP and display the Progress

I found a nice open-source FTP-Library that can upload files, change the directory etc.  (ftpLib.cs was originally written by Jaimon Mathew and modified by Dan Rolander and others).

But it lacks the feature to upload a Directory recursiv, therefore i coded a class with some Extension Methods.

I also made up a small Example:

 

Thats the code of the extension class:

/*****************************************
 * Authors of this code:
 * 
 * /
 * 
 * WhiteByte
 * 
 * Nick Russler
 * Ahmet Yüksektepe
 * Felix Rath
 * Trutz Behn
 * 
 * Redistributions of source code must retain the above copyright notice
 * No other Limitations
 ****************************************/
 
using System;
using System.Collections.Generic;
using System.Text;
using FTPLib;
using System.IO;
 
namespace FTPLib
{
    static class Extension
    {
        #region GetDirectorySize
        private static long GetDirectorySize(string p)
        {
            string[] a = Directory.GetFiles(p, "*.*");
            long b = 0;
            foreach (string name in a)
            {
                FileInfo info = new FileInfo(name);
                b += info.Length;
            }
            return b;
        }
 
        private static long GetDirectorySize(string b, Boolean recurse)
        {
            if (!recurse)
                return GetDirectorySize(b);
 
            long result = 0;
            Stack stack = new Stack();
            stack.Push(b);
 
            while (stack.Count > 0)
            {
                string dir = stack.Pop();
                try
                {
                    result += GetDirectorySize(dir);
                    foreach (string dn in Directory.GetDirectories(dir))
                    {
                        stack.Push(dn);
                    }
                }
                catch { }
            }
            return result;
        }
        #endregion
 
        /// 
        /// Try to Create a directory on the ftp server (When Exception is thrown returns false)
        /// 
        /// <param name="dir" />Directory to create
        public static bool tryMakeDir(this FTP ftp, String path)
        {
            try
            {
                ftp.MakeDir(path);
            }
            catch
            {
                return false;
            }
            return true;
        }
 
        public delegate void ProgressEvent(System.IO.FileInfo File, long BytesTotal, long FileSize, long TotalBytesDirectorySent, long TotalBytesDirectory, long StartTickCount);
 
        private static long oldBytesTotal = 0;
        private static long TotalBytesDirectory;
        private static long TotalBytesDirectorySend;
        private static long StartTickCount = 0;
 
        /// 
        /// Uploads a file and notifies through the ProgressEvent
        /// 
        /// <param name="ftp" />
        /// <param name="path" />path to the file to upload
        /// <param name="pe" />A delegate to the Callback Method
        public static void UploadFile(this FTP ftp, String path, ProgressEvent pe)
        {
            System.IO.FileInfo fi = new System.IO.FileInfo(path);
 
            StartTickCount = DateTime.Now.Ticks;
 
            ftp.OpenUpload(fi.FullName, fi.Name, false);
 
            while (ftp.DoUpload() &gt; 0)
            {
                TotalBytesDirectorySend += (ftp.BytesTotal - oldBytesTotal);
 
                oldBytesTotal = ftp.BytesTotal;
 
                if (ftp.BytesTotal == ftp.FileSize)
                    oldBytesTotal = 0;
 
                if (pe != null)
                {
                    pe(fi, ftp.BytesTotal, ftp.FileSize, ftp.BytesTotal, ftp.FileSize, StartTickCount);
                }
            }
        }
 
        private static void UploadFolderRecursively(this FTP ftp, String StartDirectory, String DirectoryToUpload, ProgressEvent pe)
        {
            System.IO.DirectoryInfo current = new System.IO.DirectoryInfo(DirectoryToUpload);
 
            String currentPath = StartDirectory + "/" + current.Name;
 
            System.IO.FileInfo[] files = null;
            System.IO.DirectoryInfo[] subDirs = null;
 
            ftp.tryMakeDir(currentPath);
 
            ftp.ChangeDir(currentPath);
 
            try
            {
                files = current.GetFiles();
            }
            catch
            {
                //
            }
 
            if (files != null)
            {
                foreach (System.IO.FileInfo fi in files)
                {
                    ftp.OpenUpload(fi.FullName, fi.Name, false);
 
                    while (ftp.DoUpload() &gt; 0)
                    {
                        TotalBytesDirectorySend += (ftp.BytesTotal - oldBytesTotal);
 
                        oldBytesTotal = ftp.BytesTotal;
 
                        if (ftp.BytesTotal == ftp.FileSize)
                            oldBytesTotal = 0;
 
                        if (pe != null)
                        {
                            pe(fi, ftp.BytesTotal, ftp.FileSize, TotalBytesDirectorySend, TotalBytesDirectory, StartTickCount);
                        }
                    }
                }
 
                subDirs = current.GetDirectories();
 
                foreach (System.IO.DirectoryInfo dirInfo in subDirs)
                {
                    UploadFolderRecursively(ftp, currentPath, dirInfo.FullName, pe);
                }
            }
        }
 
        /// 
        /// Uploads a folder Recursively and notifies through the ProgressEvent
        /// 
        /// <param name="ftp" />
        /// <param name="DirectoryToUpload" />path to the Directory to upload
        /// <param name="pe" />A delegate to the Callback Method
        public static void UploadFolderRecursively(this FTP ftp, String DirectoryToUpload, ProgressEvent pe)
        {
            TotalBytesDirectory = GetDirectorySize(DirectoryToUpload, true);
            TotalBytesDirectorySend = 0;
            StartTickCount = DateTime.Now.Ticks;
            UploadFolderRecursively(ftp, ftp.GetWorkingDirectory(), DirectoryToUpload, pe);
        }
    }
}

And here the Code of the Example:

public static FTP ftplib = null;
 
private long deltabytes = 0;
private TimeSpan deltatime = new TimeSpan(0);
 
private long updateTime = 0;
 
public void ProgressEvent(System.IO.FileInfo File, long BytesTotal, long FileSize, long TotalBytesDirectorySent, long TotalBytesDirectory, long StartTickCount)
{
	if (this.InvokeRequired)
	{
		this.BeginInvoke(new MethodInvoker(delegate() { ProgressEvent(File, BytesTotal, FileSize, TotalBytesDirectorySent, TotalBytesDirectory, StartTickCount); }));
		return;
	}
 
	TimeSpan elapsedSpan = new TimeSpan(DateTime.Now.Ticks - StartTickCount);
 
	labelFilename.Text = "Filename: " + File.FullName;
	labelCurrentSend.Text = "Current: " + (BytesTotal / 1024).ToString() + "/" + (FileSize / 1024).ToString() + " KB";
	labelTotal.Text = "Total: " + (TotalBytesDirectorySent / 1024).ToString() + "/" + (TotalBytesDirectory / 1024).ToString() + " KB";
	labelElapsed.Text = "Elapsed: " + string.Format("{0:D2}:{1:D2}:{2:D2}", elapsedSpan.Hours, elapsedSpan.Minutes, elapsedSpan.Seconds);
 
	if (progressBar1.Value != (int)((BytesTotal * 100) / FileSize))
		progressBar1.Value = (int)((BytesTotal * 100) / FileSize);
 
	if (progressBar2.Value != (int)((TotalBytesDirectorySent * 100) / TotalBytesDirectory))
		progressBar2.Value = (int)((TotalBytesDirectorySent * 100) / TotalBytesDirectory);
 
	if ((new TimeSpan(DateTime.Now.Ticks - updateTime).TotalMilliseconds &gt; 200) || (TotalBytesDirectorySent == TotalBytesDirectory))
	{
		updateTime = DateTime.Now.Ticks;
 
		deltabytes = TotalBytesDirectorySent - deltabytes;
		deltatime = elapsedSpan.Subtract(deltatime);
 
		if (deltatime.Seconds &gt; 0)
		{
			labelSpeed.Text = "Speed: " + (deltabytes / deltatime.Seconds / 1024).ToString() + " KB/s";
 
			TimeSpan t = TimeSpan.FromSeconds((TotalBytesDirectory - deltabytes) / (deltabytes / deltatime.Seconds));
			labelRemaining.Text = "Remaining: " + string.Format("{0:D2}:{1:D2}:{2:D2}", t.Hours, t.Minutes, t.Seconds);
		}
	}
 
	if (BytesTotal == FileSize)
	{
		deltabytes = 0;
		deltatime = new TimeSpan(0);
	}
}
 
private void buttonUpload_Click(object sender, EventArgs e)
{
	if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
	{
		ftplib = new FTP(textBoxHost.Text, textBoxUsr.Text, textBoxPwd.Text);
 
		ftplib.Connect();
 
		new Thread(delegate()
		{
			ftplib.UploadFolderRecursively(folderBrowserDialog1.SelectedPath, ProgressEvent);
		}).Start();
	}
}
 
private void buttonStop_Click(object sender, EventArgs e)
{
	Application.Exit();
}

Download Example (Binaries&Sources)

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.