我编写了以下代码来检测目录是否存在。 DirectoryExists
方法接受完全限定或相对路径。
public bool DirectoryExists(string directory)
{
try
{
FtpWebRequest request = GetRequest(directory);
request.Method = WebRequestMethods.Ftp.ListDirectory;
using (FtpWebResponse response = request.GetResponse() as FtpWebResponse)
using (StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.ASCII))
{
sr.ReadToEnd();
}
return true;
}
catch { }
return false;
}
protected FtpWebRequest GetRequest(string filename = "")
{
FtpWebRequest request = WebRequest.Create(_host.GetUrl(filename)) as FtpWebRequest;
request.Credentials = new NetworkCredential(Username, Password);
request.Proxy = null;
request.KeepAlive = false;
return request;
}
注意:_host.GetUrl(filename)
返回指定目录或文件名的完全限定路径。就我而言,这是ftp://www.mydomain.com/Articles/controls/precisely-defining-kilobytes-megabytes-and-gigabytes
。
这段代码已经工作了好几个月。但突然间它停止了工作。现在,当目录不存在时,DirectoryExists
中没有引发异常。 sr.ReadToEnd()
只返回一个空字符串。
我发布了一个类似的问题,有人建议我应该始终将/
添加到我的路径末尾。我试过了,并且认为我有一次异常,但现在没有引发异常。
我不知道我正在与之通信的FTP服务器上的行为是否发生了变化。再次,当我写这篇文章时,这种方法很好,现在却没有。
如何判断FTP目录是否存在?
修改
在致电ReadToEnd()
后检查回复,我看到了:
BannerMessage =“220 Microsoft FTP服务\ r \ n”
的ContentLength = -1
ExitMessage =“221 Goodbye。\ r \ n”
的StatusCode = ClosingData
StatusDescription =“226传输完成。\ r \ n”
WelcomeMessage =“230用户已登录。\ r \ n”
更新
最终,我发现大多数人一直在推荐我最初做的变化。这对Hans Passant的建议很重要,因为服务器存在问题。我试图让他们看看这个,但他们似乎对整个讨论感到困惑。我知道他们正在使用微软服务器,我很怀疑我能从他们那里获得解决方案。
如果所有其他方法都失败了,我认为答案是做一个父目录的列表,这需要一些额外的工作来处理案例,例如当有问题的目录是根目录时,以及父进程没有的情况存在。
答案 0 :(得分:6)
当您要求提供不存在的目录/文件时,FTP服务器将回复550条消息。这个550在.NET中被转换为例外。
关于您提供的代码,我没有看到在生产中使用StreamReader的原因。一个简单的修改如下:
public bool DirectoryExists(string directory)
{
try
{
FtpWebRequest request = GetRequest(directory);
request.Method = WebRequestMethods.Ftp.ListDirectory;
return request.GetResponse() != null;
}
catch
{
return false;
}
}
我保持异常处理原样(缺失),但我建议你继续处理它,因为有很多不同的情况需要捕获与ftp响应无关。
如果目录不存在,request.GetResponse()将生成异常。
我尝试使用以下路径获得真实的回报:
最后一个是现有但空目录
ftp://ftp.mozilla.org/pub/data/bloat-reports2/ 返回false
有一个很大但有关的尾随/路径。
mozilla.org是pub目录下的零字节长度文件
ftp://ftp.mozilla.org/pub/mozilla.org返回true
ftp://ftp.mozilla.org/pub/mozilla.org/返回false然后是真的?????
此行为与您描述的内容类似。您可以在浏览器上轻松地重现它。我建议你用你自己的路径做同样的事情并检查目录的内容。如果你有空文件,删除它们或用空格替换它们的内容,最后检查你的代码,以确保你不会创建新文件或重新创建零字节长度。
我希望这会有所帮助。
<强>更新强>
没有新闻,坏消息!我假设上述任何内容都没有帮助你。也许通过在你的道路上上升一级将解决问题。我们的想法是获取父目录的列表并检查它的子名称。如果父路径有效,则应始终返回非空字符串。代码如下:
static bool DirectoryExists(string directory)
{
try
{
directory = GetRequest(directory);
string
parent = directory.Substring(0, directory.TrimEnd('/').LastIndexOf('/') + 1),
child = directory.Substring(directory.TrimEnd('/').LastIndexOf('/') + 1).TrimEnd('/');
FtpWebRequest request = GetRequest(parent);
request.Method = WebRequestMethods.Ftp.ListDirectory;
using (FtpWebResponse response = request.GetResponse() as FtpWebResponse)
{
if (response == null)
return false;
string data = new StreamReader(response.GetResponseStream(), true).ReadToEnd();
return data.IndexOf(child, StringComparison.InvariantCultureIgnoreCase) >= 0;
}
}
catch
{
return false;
}
}
正如您所看到的,无需担心拖尾斜杠。
警告:代码不会涵盖同一路径下子目录和名称相同的文件名。
答案 1 :(得分:0)
这可能是因为您的服务器上安装了FTP服务器软件。
否则,您可能需要查看response.StatusCode以查看是否有任何提示。
http://msdn.microsoft.com/en-us/library/system.net.ftpstatuscode(v=vs.110).aspx
最后,如果所有这些都不起作用,请尝试在该不存在的目录上写一个愚蠢的文本文件。
答案 2 :(得分:0)
我有类似的代码,可以通过FTP将项目部署到IIS 6 / Windows 2003 Server。这工作正常,直到我指向IIS7 / Windows 2008服务器。我开始看到你做的完全相同的行为。我调试它并最终将我的代码更改为以下内容。这是我的代码的直接片段。如果你愿意,我可以从它调用的方法中包含源代码,但我认为你理解这些操作。
try
{
//Get a recursive FTP Listing
items = GetFtpListing(target, true);
}
catch(WebException e)
{
if (string.Equals(e.Message, "The remote server returned an error: (550) File unavailable (e.g., file not found, no access)."))
{
CreateRemoteDirectory(target);
items = GetFtpListing(target, true);
}
else
{
throw e;
}
}
GetFtpListing
List<string> ftpRawList = new List<string>();
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
request.Timeout = 60000;
request.ReadWriteTimeout = 60000;
request.Credentials = this.credentials;
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
Stream data = response.GetResponseStream();
using (StreamReader reader = new StreamReader(data))
{
string responseString = reader.ReadToEnd();
ftpRawList.AddRange(responseString.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
}
答案 3 :(得分:0)
我使用以下内容检查ftp连接凭据是否有效。您可以使用相同的方法来检查目录是否存在。如果url,username和password正确,则返回true。
URL:您在此处指定目录路径。 user:ftp用户名 密码:ftp密码
public static bool isValidConnection(string url, string user, string password, ref string errorMessage = "")
{
try {
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Credentials = new NetworkCredential(user, password);
request.KeepAlive = false;
request.UsePassive = true;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
} catch (WebException ex) {
errorMessage = ex.Message;
return false;
}
return true;
}
答案 4 :(得分:0)
一种方法是列出许多解决方案中存在的目录内容,但在我的情况下,我还必须读取数据内容,以便服务器检查目录。如果目录不存在,则抛出webException,应该解释为从意外错误中过滤掉。
这是我的解决方案:
bool directoryExists(string path)
{
bool? exists = null;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
request.Method = WebRequestMethods.Ftp.ListDirectory;
request.Credentials = new NetworkCredential("username", "*****");
FtpWebResponse response = null;
try
{
response = (FtpWebResponse)request.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string str = sr.ReadLine(); //Just needs to read one line to fire check on server
sr.Close();
return true;
}
}
catch (WebException ex)
{
var r = (FtpWebResponse)ex.Response;
if (r.StatusCode ==
FtpStatusCode.ActionNotTakenFileUnavailable)
{
//Does not exist
return false;
}
throw; //if error is not related to directory existence then the exception needs to be treated above.
}
finally
{
if (response != null)
response.Close();
}
return false;
}
我定位的FTP服务器我知道是一个Windows服务器,但我无法访问版本信息。