There's no standard FTP command to retrieve a directory size.
You have to recursively iterate all subdirectories and files and sum the sizes.
This is not easy with .NET framework/FtpWebRequest
, as it does not support the MLSD
command, which is the only portable way to retrieve directory listing with file attributes in FTP protocol.
All you can do is to use LIST
command (ListDirectoryDetails
) and try to parse a server-specific listing. Many FTP servers use *nix-style listing. But many servers use a different format. The following example uses *nix format:
static long CalculateFtpDirectorySize(string url, NetworkCredential credentials)
{
FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url);
listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
listRequest.Credentials = credentials;
List<string> lines = new List<string>();
using (var listResponse = (FtpWebResponse)listRequest.GetResponse())
using (Stream listStream = listResponse.GetResponseStream())
using (StreamReader listReader = new StreamReader(listStream))
{
while (!listReader.EndOfStream)
{
lines.Add(listReader.ReadLine());
}
}
long result = 0;
foreach (string line in lines)
{
string[] tokens =
line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
string name = tokens[8];
string permissions = tokens[0];
string fileUrl = url + name;
if (permissions[0] == 'd')
{
result += CalculateFtpDirectorySize(fileUrl + "/", credentials);
}
else
{
result += long.Parse(tokens[4]);
}
}
return result;
}
Use it like:
var credentials = new NetworkCredential("username", "password");
long size = CalculateFtpDirectorySize("ftp://ftp.example.com/", credentials);
If your server uses DOS/Windows listing format, see C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response
Alternatively you can use a 3rd party FTP client implementation that supports the modern MLSD
command.
For example WinSCP .NET assembly supports that.
And it even has handy Session.EnumerateRemoteFiles
method, which makes calculating directory size easy task:
var opts = EnumerationOptions.AllDirectories;
var files = session.EnumerateRemoteFiles("/", null, opts);
long size = files.Select(fileInfo => fileInfo.Length).Sum();
A complete code would be like:
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "ftp.example.com",
UserName = "username",
Password = "password",
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
var opts = EnumerationOptions.AllDirectories;
var files = session.EnumerateRemoteFiles("/", null, opts);
long size = files.Select(fileInfo => fileInfo.Length).Sum();
}
(I'm the author of WinSCP)