How to Check If File Exists on Ftp Before Ftpwebrequest

How to check if file exists on FTP before FtpWebRequest

var request = (FtpWebRequest)WebRequest.Create
("ftp://ftp.domain.com/doesntexist.txt");
request.Credentials = new NetworkCredential("user", "pass");
request.Method = WebRequestMethods.Ftp.GetFileSize;

try
{
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
FtpWebResponse response = (FtpWebResponse)ex.Response;
if (response.StatusCode ==
FtpStatusCode.ActionNotTakenFileUnavailable)
{
//Does not exist
}
}

As a general rule it's a bad idea to use Exceptions for functionality in your code like this, however in this instance I believe it's a win for pragmatism. Calling list on the directory has the potential to be FAR more inefficient than using exceptions in this way.

If you're not, just be aware it's not good practice!

EDIT: "It works for me!"

This appears to work on most ftp servers but not all. Some servers require sending "TYPE I" before the SIZE command will work. One would have thought that the problem should be solved as follows:

request.UseBinary = true;

Unfortunately it is a by design limitation (big fat bug!) that unless FtpWebRequest is either downloading or uploading a file it will NOT send "TYPE I". See discussion and Microsoft response here.

I'd recommend using the following WebRequestMethod instead, this works for me on all servers I tested, even ones which would not return a file size.

WebRequestMethods.Ftp.GetDateTimestamp

Check if file exists on FTP - Don't know the name of the file

You can list out the file names from the FTP. Like Below...

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpURL);
request.Method = WebRequestMethods.Ftp.ListDirectory;

FtpWebResponse response = (FtpWebResponse) request.GetResponse();
using (Stream respStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(respStream);
//Read each file name from the response
for (string fname = reader.ReadLine(); fname != null; fname = reader.ReadLine())
{
// Add the file name into a list
}
}

If the list count is 0 then there is no file available. Also you will get the each file name in a list from the single request.

Iterate the list values using foreach loop. And make the above code as a method. Pass the File name to the method.

You can also do make sure particular file name is exists or not in the list.

Note: In the above code no need to provide the file name to the Url.

how to check if file exist in a folder on ftp in c#

Based on your other question to get a list of files from ftp, you can check if the file you want to check is in that list:

Var fileNameToCkeck = "myfile.txt";

var utility= new FtpUtility();
utility.UserName = "...";
utility.Password = "...";
utility.Path = "...";

If (utility.ListFiles().Contains(fileNameToCkeck))
{
//The file exists
}

Or if you want to know if that path has any file:

If (utility.ListFiles().Count() > 0)
{
//The folder contains files
}

And here is the code for FtpUtility

public class FtpUtility
{
public string UserName { get; set; }
public string Password { get; set; }
public string Path { get; set; }
public List<string> ListFiles()
{
var request = (FtpWebRequest)WebRequest.Create(Path);
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
request.Credentials = new NetworkCredential(UserName, Password);
List<string> files = new List<string>();
using (var response = (FtpWebResponse)request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var reader = new StreamReader(responseStream);
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (string.IsNullOrWhiteSpace(line) == false)
{
var fileName = line.Split(new[] { ' ', '\t' }).Last();
if (!fileName.StartsWith("."))
files.Add(fileName);
}
}
return files;
}
}
}
}

How to check if file exists in remote folder via FTP?

It would be easier to just try and download the file. If you get StatusCode indicating that the file does not exist, you know it was not there.

Probably less work than filtering the result of ListDirectoryDetails.

Update

To clarify, all you need to do is this:

FtpWebResponse response = (FtpWebResponse) request.GetResponse();
bool fileExists = (response.StatusCode != BAD_COMMAND);

I think BAD_COMMAND would be FtpStatusCode.CantOpenData but I'm not sure. That's easily tested.

FTP Check if file exist when Uploading and if it does rename it in C#

It's not particularly elegant as I just threw it together, but I guess this is pretty much what you need?

You just want to keep trying your requests until you get a "ActionNotTakenFileUnavailable", so you know your filename is good, then just upload it.

        string destination = "ftp://something.com/";
string file = "test.jpg";
string extention = Path.GetExtension(file);
string fileName = file.Remove(file.Length - extention.Length);
string fileNameCopy = fileName;
int attempt = 1;

while (!CheckFileExists(GetRequest(destination + "//" + fileNameCopy + extention)))
{
fileNameCopy = fileName + " (" + attempt.ToString() + ")";
attempt++;
}

// do your upload, we've got a name that's OK
}

private static FtpWebRequest GetRequest(string uriString)
{
var request = (FtpWebRequest)WebRequest.Create(uriString);
request.Credentials = new NetworkCredential("", "");
request.Method = WebRequestMethods.Ftp.GetFileSize;

return request;
}

private static bool checkFileExists(WebRequest request)
{
try
{
request.GetResponse();
return true;
}
catch
{
return false;
}
}

Edit: Updated so this will work for any type of web request and is a little slimmer.

Checking if file exist or not on ftp server before downloading it

My understanding is that you have to create a new FtpWebRequest for each request you make. So before setting the Method again you'd have to create a new one and set the credentials again. So pretty much that you'd have to repeat the following two lines:

ftpRequest = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpPath + fileName));
ftpRequest.Credentials = new NetworkCredential(userName, password);

Check if is file or folder on FTP

There's no way to identify if a directory entry is a sub-directory of file in a portable way with the FtpWebRequest or any other built-in feature of .NET framework. The FtpWebRequest unfortunately does not support the MLSD command, which is the only portable way to retrieve directory listing with file attributes in FTP protocol. See also Checking if object on FTP server is file or directory.

Your options are:

  • Do an operation on a file name that is certain to fail for a file and succeeds for a directory (or vice versa). I.e. you can try to download the "name". If that succeeds, it's a file, if that fails, it's a directory.
  • You may be lucky and in your specific case, you can tell a file from a directory by a file name (i.e. all your files have an extension, while subdirectories do not)
  • You use a long directory listing (LIST command = ListDirectoryDetails method) and try to parse a server-specific listing. Many FTP servers use *nix-style listing, where you identify a directory by the d at the very beginning of the entry. But many servers use a different format.

    For some examples of implementing the parsing, see:

    *nix format: Parsing FtpWebRequest ListDirectoryDetails line

    DOS/Windows format: C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response


If you want to avoid troubles with parsing the server-specific directory listing formats, use a 3rd party library that supports the MLSD command and/or parsing various LIST listing formats; and recursive downloads.

For example with WinSCP .NET assembly you can use Sesssion.ListDirectory:

// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "example.com",
UserName = "user",
Password = "mypassword",
};

using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);

RemoteDirectoryInfo directory = session.ListDirectory("/home/martin/public_html");

foreach (RemoteFileInfo fileInfo in directory.Files)
{
if (fileInfo.IsDirectory)
{
// directory
}
else
{
// file
}
}
}

Internally, WinSCP uses the MLSD command, if supported by the server. If not, it uses the LIST command and supports dozens of different listing formats.

(I'm the author of WinSCP)



Related Topics



Leave a reply



Submit