如何从 .NET 应用程序中的 FTP 协议获取目录文件大小
Posted
技术标签:
【中文标题】如何从 .NET 应用程序中的 FTP 协议获取目录文件大小【英文标题】:How to get a directories file size from an FTP protocol in a .NET application 【发布时间】:2011-12-15 01:19:21 【问题描述】:我目前正在制作一个小型 .NET 控制台应用程序,以将我的一些文件自动备份到我的服务器上。我遇到的问题是我遇到了一些恶劣的天气,导致一些电力和网络中断。在此期间,我注意到我的大部分文件没有通过或损坏。我想知道是否有办法获取另一端文件夹的大小,并查看文件名、文件数和总目录大小是否匹配。我已经尝试过 WinSCP 和 NcFTP 作为传输文件的方法,但我还没有看到任何关于获取适当文件大小的信息。
这几乎是一个窗口到窗口的传输,所以如果有一个命令行参数可以通过 FTP 客户端返回一个大小,那就太好了。
【问题讨论】:
为什么选择 FTP?您对其他协议持开放态度吗? 根据其他协议,我可以试一试。因为速度,我只做了 FTP。 【参考方案1】:没有标准的 FTP 命令来检索目录大小。
您必须递归迭代所有子目录和文件并对大小求和。
这对于 .NET framework/FtpWebRequest
来说并不容易,因为它不支持 MLSD
命令,这是在 FTP 协议中检索具有文件属性的目录列表的唯一可移植方式。
您所能做的就是使用LIST
命令(ListDirectoryDetails
)并尝试解析特定于服务器的列表。许多 FTP 服务器使用 *nix 样式的列表。但是许多服务器使用不同的格式。以下示例使用 *nix 格式:
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;
像这样使用它:
var credentials = new NetworkCredential("username", "password");
long size = CalculateFtpDirectorySize("ftp://ftp.example.com/", credentials);
如果您的服务器使用 DOS/Windows 列表格式,请参阅C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response
或者,您可以使用支持现代MLSD
命令的第 3 方 FTP 客户端实现。
例如WinSCP .NET assembly 支持。
它甚至还有方便的Session.EnumerateRemoteFiles
方法,这使得计算目录大小变得容易:
var opts = EnumerationOptions.AllDirectories;
var files = session.EnumerateRemoteFiles("/", null, opts);
long size = files.Select(fileInfo => fileInfo.Length).Sum();
完整的代码如下:
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();
(我是 WinSCP 的作者)
【讨论】:
【参考方案2】:没有标准的方法来请求“此目录中文件的总大小”。您可以通过SIZE file.txt
单独询问每个文件大小,也可以询问整个目录的ls -l
并解析文件大小。
【讨论】:
这种方法对于有大文件的目录并试图通过网络解析它是乏味的,但总的来说这似乎有效。感谢您的帮助。【参考方案3】:我认为最好的办法是获取完整的文件列表,然后一次发送一个。如果在传输过程中连接失败,则该文件上传将失败。如果文件上传成功,您可以从列表中删除该文件名。
正如您在标签中提到的 NET,也许您应该查看 here 以获取如何在 C# 中执行它的示例。 VB.Net 将是类似的,但它会给你一个想法。
可以得到here所示的目录列表。
【讨论】:
以上是关于如何从 .NET 应用程序中的 FTP 协议获取目录文件大小的主要内容,如果未能解决你的问题,请参考以下文章