38

How to calculate size of FTP folder? Do you know any tool or programmatic way in C#?

Rémi
  • 3,867
  • 5
  • 28
  • 44
jlp
  • 9,800
  • 16
  • 53
  • 74

10 Answers10

98

If you have FileZilla, you can use this trick:

  • click on the folder(s) whose size you want to calculate
  • click on Add files to queue

This will scan all folders and files and add them to the queue. Then look at the queue pane and below it (on the status bar) you should see a message indicating the queue size.

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
janusman
  • 1,081
  • 7
  • 4
  • 5
    Very good solution. This way, you can get the total number of files and the total size without Downloading any file. The [FTP command](http://en.wikipedia.org/wiki/List_of_FTP_commands) used by Filezilla is MLSD (recursively) if anybody is curious about it. – Fabien Quatravaux Apr 24 '14 at 09:04
  • 3
    Note that you need to have a valid destination selected in the local directory tree pane (otherwise _Add files to queue_ will be greyed out). – jbaums Mar 15 '15 at 23:33
  • To sort the queue by size, click the "Size" column heading – BallpointBen Mar 12 '21 at 17:32
26

You can use the du command in lftp for this purpose, like this:

echo "du -hs ." | lftp example.com 2>&1

This will print the current directory's disk size incl. all subdirectories, in human-readable format (-h) and omitting output lines for subdirectories (-s). stderr output is rerouted to stdout with 2>&1 so that it is included in the output.

However, lftp is a Linux-only software, so to use it from C# under Windows you would need to install it in the integrated Windows Subsystem for Linux (WSL) or using Cygwin or MSYS2. (Thanks to the commenters for the hints!)

The lftp du command documentation is missing from its manpage, but available within the lftp shell with the help du command. For reference, I copy its output here:

lftp :~> help du
Usage: du [options] <dirs>
Summarize disk usage.
 -a, --all             write counts for all files, not just directories
     --block-size=SIZ  use SIZ-byte blocks
 -b, --bytes           print size in bytes
 -c, --total           produce a grand total
 -d, --max-depth=N     print the total for a directory (or file, with --all)
                       only if it is N or fewer levels below the command
                       line argument;  --max-depth=0 is the same as
                       --summarize
 -F, --files           print number of files instead of sizes
 -h, --human-readable  print sizes in human readable format (e.g., 1K 234M 2G)
 -H, --si              likewise, but use powers of 1000 not 1024
 -k, --kilobytes       like --block-size=1024
 -m, --megabytes       like --block-size=1048576
 -S, --separate-dirs   do not include size of subdirectories
 -s, --summarize       display only a total for each argument
     --exclude=PAT     exclude files that match PAT
tanius
  • 14,003
  • 3
  • 51
  • 63
7

WinSCP (free GUI on Microsoft Windows):

enter image description here

enter image description here

Franck Dernoncourt
  • 77,520
  • 72
  • 342
  • 501
5

If you just need the work done, then SmartFTP might help you, it also has a PHP and ASP script to get the total folder size by recursively going through all the files.

zengr
  • 38,346
  • 37
  • 130
  • 192
2

You could send the LIST command which should give you a list of files in the directory and some info about them (fairly certain the size is included), which you could then parse out and add up.

Depends on how you connect to the server, but if you're useing the WebRequest.Ftp class there's the ListDirectoryDetails method to do this. See here for details and here for some sample code.

Just be aware, if you want to have the total size including all subdirectories, I think you'll have to enter each subdirectory and call it recursively so it could be quite slow. It can be quite slow thought so normally I'd recommended, if possible, to have a script on the server calculate the size and return the result in some way (possibly storing it in a file you could download and read).

Edit: Or if you just mean that you'd be happy with a tool that does it for you, I think FlashFXP does it and probably other advanced FTP clients will as well. Or if it's a unix server I have a vague memory that you could just login and type ls -laR or something to get a recursive directory listing.

Hans Olsson
  • 54,199
  • 15
  • 94
  • 116
1

I use the FTPS library from Alex Pilotti with C# to execute some FTP commands in a few production environments. The library works well, but you have to recursively get a list of files in the directory and add their sizes together to get the result. This can be a bit time consuming on some of our larger servers (sometimes 1-2 min) with complex file structures.

Anyway, this is the method I use with his library:

/// <summary>
/// <para>This will get the size for a directory</para>
/// <para>Can be lengthy to complete on complex folder structures</para>
/// </summary>
/// <param name="pathToDirectory">The path to the remote directory</param>
public ulong GetDirectorySize(string pathToDirectory)
{
    try
    {
        var client = Settings.Variables.FtpClient;
        ulong size = 0;

        if (!IsConnected)
            return 0;

        var dirList = client.GetDirectoryList(pathToDirectory);
        foreach (var item in dirList)
        {
            if (item.IsDirectory)
                size += GetDirectorySize(string.Format("{0}/{1}", pathToDirectory, item.Name));
            else
                size += item.Size;
        }
        return size;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    return 0;
}
jsmith
  • 976
  • 8
  • 19
1

Simplest and Efficient way to Get FTP Directory Size with it's all Contents recursively.

var size = FtpHelper.GetFtpDirectorySize("ftpURL", "userName", "password");

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

public static class FtpHelper
{
    public static long GetFtpDirectorySize(Uri requestUri, NetworkCredential networkCredential, bool recursive = true)
    {
        //Get files/directories contained in CURRENT directory.
        var directoryContents = GetFtpDirectoryContents(requestUri, networkCredential);

        long ftpDirectorySize = default(long); //Set initial value of the size to default: 0
        var subDirectoriesList = new List<Uri>(); //Create empty list to fill it later with new founded directories.

        //Loop on every file/directory founded in CURRENT directory. 
        foreach (var item in directoryContents)
        {
            //Combine item path with CURRENT directory path.
            var itemUri = new Uri(Path.Combine(requestUri.AbsoluteUri + "\\", item));
            var fileSize = GetFtpFileSize(itemUri, networkCredential); //Get item file size.

            if (fileSize == default(long)) //This means it has no size so it's a directory and NOT a file.
                subDirectoriesList.Add(itemUri); //Add this item Uri to subDirectories to get it's size later.
            else //This means it has size so it's a file.
                Interlocked.Add(ref ftpDirectorySize, fileSize); //Add file size to overall directory size.
        }

        if (recursive) //If recursive true: it'll get size of subDirectories files.
            //Get size of selected directory and add it to overall directory size.
            Parallel.ForEach(subDirectoriesList, (subDirectory) => //Loop on every directory
        Interlocked.Add(ref ftpDirectorySize, GetFtpDirectorySize(subDirectory, networkCredential, recursive)));

        return ftpDirectorySize; //returns overall directory size.
    }
    public static long GetFtpDirectorySize(string requestUriString, string userName, string password, bool recursive = true)
    {
        //Initialize Uri/NetworkCredential objects and call the other method to centralize the code
        return GetFtpDirectorySize(new Uri(requestUriString), GetNetworkCredential(userName, password), recursive);
    }

    public static long GetFtpFileSize(Uri requestUri, NetworkCredential networkCredential)
    {
        //Create ftpWebRequest object with given options to get the File Size. 
        var ftpWebRequest = GetFtpWebRequest(requestUri, networkCredential, WebRequestMethods.Ftp.GetFileSize);

        try { return ((FtpWebResponse)ftpWebRequest.GetResponse()).ContentLength; } //Incase of success it'll return the File Size.
        catch (Exception) { return default(long); } //Incase of fail it'll return default value to check it later.
    }
    public static List<string> GetFtpDirectoryContents(Uri requestUri, NetworkCredential networkCredential)
    {
        var directoryContents = new List<string>(); //Create empty list to fill it later.
        //Create ftpWebRequest object with given options to get the Directory Contents. 
        var ftpWebRequest = GetFtpWebRequest(requestUri, networkCredential, WebRequestMethods.Ftp.ListDirectory);
        try
        {
            using (var ftpWebResponse = (FtpWebResponse)ftpWebRequest.GetResponse()) //Excute the ftpWebRequest and Get It's Response.
            using (var streamReader = new StreamReader(ftpWebResponse.GetResponseStream())) //Get list of the Directory Contentss as Stream.
            {
                var line = string.Empty; //Initial default value for line
                while (!string.IsNullOrEmpty(line = streamReader.ReadLine())) //Read current line of Stream.
                    directoryContents.Add(line); //Add current line to Directory Contentss List.
            }
        }
        catch (Exception) { throw; } //Do nothing incase of Exception occurred.
        return directoryContents; //Return all list of Directory Contentss: Files/Sub Directories.
    }
    public static FtpWebRequest GetFtpWebRequest(Uri requestUri, NetworkCredential networkCredential, string method = null)
    {
        var ftpWebRequest = (FtpWebRequest)WebRequest.Create(requestUri); //Create FtpWebRequest with given Request Uri.
        ftpWebRequest.Credentials = networkCredential; //Set the Credentials of current FtpWebRequest.

        if (!string.IsNullOrEmpty(method))
            ftpWebRequest.Method = method; //Set the Method of FtpWebRequest incase it has a value.
        return ftpWebRequest; //Return the configured FtpWebRequest.
    }
    public static NetworkCredential GetNetworkCredential(string userName, string password)
    {
        //Create and Return NetworkCredential object with given UserName and Password.
        return new NetworkCredential(userName, password);
    }
}
BenSabry
  • 483
  • 4
  • 10
1

As the answer by @FranckDernoncourt shows, if you want a GUI tool, you can use WinSCP GUI. Particularly its folder properties dialog.


If you need a code, you can use WinSCP too. Particularly with WinSCP .NET assembly and its Session.EnumerateRemoteFiles method it is easy to implement in many languages, including C#.

It is also doable with .NET built-in FtpWebRequest, but that's lot more work.

Both are covered in How to get a directories file size from an FTP protocol in a .NET application.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
-1

You can use The FileZilla client. Download here: https://filezilla-project.org/download.php?type=client

If you want more readable size go to:

Edit -> Settings -> Interface -> filesize format -> size formatting -> select binary prefixes using SI symbols.

When you select a directory you can see its size.

size can be seen here

Trekco
  • 1,246
  • 6
  • 17
Muhammad Ahmed
  • 144
  • 1
  • 8
-2

Just use FTP "SIZE" command...

Swapnil Gupta
  • 8,751
  • 15
  • 57
  • 75