This project is read-only.

CreateDirectory() tries to create directory twice

Jan 22, 2013 at 11:52 PM
Edited Jan 22, 2013 at 11:53 PM

I have run into an issue where I am checking if a folder exists and creating it if not, however looking at the log it is trying tr create it twice resulting in a "550 Can't create directory: File exists" error.

I am using the version from the download page (page says its 12.12.13.3, zip file is 12.12.13.0) Version in Visual studio shows 1.0.4730.14476

my code looks like this 

if (!_ftpConn.DirectoryExists(folder))
    _ftpConn.CreateDirectory(folder, true);

And the log file is

220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
220-You are user number 23 of 500 allowed.
220-Local time is now 15:48. Server port: 21.
220-This is a private system - No anonymous login
220 You will be disconnected after 3 minutes of inactivity.
USER Username
331 User Username OK. Password required
PASS 
230 OK. Current restricted directory is /
FEAT
211-Extensions supported:
 EPRT
 IDLE
 MDTM
 SIZE
 MFMT
 REST STREAM
 MLST type*;size*;sizd*;modify*;UNIX.mode*;UNIX.uid*;UNIX.gid*;unique*;
 MLSD
 AUTH TLS
 PBSZ
 PROT
 UTF8
 ESTA
 PASV
 EPSV
 SPSV
 ESTP
211 End.
OPTS UTF8 ON
200 OK, UTF-8 enabled
PWD
257 "/" is your current location
CWD /samples/2/3/4/23414
250 OK. Current directory is /samples/2/3/4/23414
CWD /
250 OK. Current directory is /
PWD
257 "/" is your current location
CWD /samples/2/3/4/23402
550 Can't change directory to /samples/2/3/4/23402: No such file or directory
PWD
257 "/" is your current location
CWD /samples/2/3/4/23402
550 Can't change directory to /samples/2/3/4/23402: No such file or directory
PWD
257 "/" is your current location
CWD /samples/2/3/4
250 OK. Current directory is /samples/2/3/4
CWD /
250 OK. Current directory is /
PWD
257 "/" is your current location
CWD /samples/2/3/4/23402
550 Can't change directory to /samples/2/3/4/23402: No such file or directory
MKD /samples/2/3/4/23402
257 "/samples/2/3/4/23402" : The directory was successfully created
MKD /samples/2/3/4/23402
550 Can't create directory: File exists

Thanks for any help, for now I'm just catching that exception and ignoring it.

Jan 23, 2013 at 3:01 PM

Thanks, I'll look into the bug and see if I can figure out what's happening.

Jan 23, 2013 at 3:21 PM

I'm not able to reproduce this problem, my code looks like this:

static void CreateDirectoryBugTest() {
            string dir = "/samples/2/3/4/23402";

            using (FtpClient cl = new FtpClient()) {
                cl.Credentials = new NetworkCredential(m_user, m_pass);
                cl.Host = m_host;
                cl.Connect();

                if (!cl.DirectoryExists(dir))
                    cl.CreateDirectory(dir, true);
            }
        }

And the transaction log looks like this:

PWD
257 "/" is current directory.
CWD /samples/2/3/4/23402
550 CWD failed. "/samples/2/3/4/23402": directory not found.
PWD
257 "/" is current directory.
CWD /samples/2/3/4
250 CWD successful. "/samples/2/3/4" is current directory.
CWD /
250 CWD successful. "/" is current directory.
PWD
257 "/" is current directory.
CWD /samples/2/3/4/23402
550 CWD failed. "/samples/2/3/4/23402": directory not found.
MKD /samples/2/3/4/23402
257 "/samples/2/3/4/23402" created successfully

Jan 23, 2013 at 9:30 PM

Thanks for the reply, I am genuinely stumped, I created a new project to test this again and it works in there using your code and a stripped down version of mine. The only difference being that mine used a global FtpClient that was declared when the class was created. I have rearranged my code to use the Using structure. but am still getting the error in my original program. 

Here is the full method that does the upload

private bool DoUpload(Product product)
        {
            var folder = string.Format("/samples/{0:#/#/#}/{1}/", int.Parse(product.SKU.ToString().Substring(0, 3)), product.SKU);
            var track = 1;
            var ret = true;

            foreach (var file in product.Files)
            {
                var uFileName = string.Format("{0}{1}-{2}.mp3", folder, product.SKU, track);
                Stream istream = null;
                var buf = new byte[8192];

                using (var _ftpConn = new FtpClient())
                {
                    _ftpConn.Host = "www.site.com";
                    _ftpConn.Credentials = new NetworkCredential("ftpusername", "ftppassword");
                    _ftpConn.Connect();

                    //Make the directory if not created
                    try
                    {
                        if (!_ftpConn.DirectoryExists(folder))
                            _ftpConn.CreateDirectory(folder, true);
                    }
                    catch (FtpCommandException fex)
                    {
                        Debug.WriteLine("Hack: Duplicate Folder Creation");
                    }


                    //Check if file exists already
                    if (_ftpConn.FileExists(uFileName))
                        _ftpConn.DeleteFile(uFileName);

                    //Upload the file
                    using (var ostream = _ftpConn.OpenWrite(uFileName))
                    {
                        try
                        {
                            istream = new FileStream(file.LocalFilePath + file.FileName, FileMode.Open, FileAccess.Read);
                            var read = 0;
                            while ((read = istream.Read(buf, 0, buf.Length)) > 0)
                            {
                                ostream.Write(buf, 0, read);
                                Debug.Write("*");
                            }
                            file.FileServerPath = uFileName;
                            track++;
                            Debug.WriteLine("*");
                        }
                        catch (Exception ex)
                        {
                            ret = false;
                            Debug.WriteLine(ex.ToString());
                            break;
                        }
                        finally
                        {
                            if (istream != null)
                                istream.Close();

                            if (ostream != null)
                                ostream.Close();
                        }
                    }
                }
            }
            return ret;
        }

It might just be that i have been looking at the same code for too long that I'm missing something obvious, still learning C# :)

 

Partial FTP Log

200 OK, UTF-8 enabled
PWD
257 "/" is your current location
CWD /samples/2/3/4/23414
550 Can't change directory to /samples/2/3/4/23414: No such file or directory
PWD
257 "/" is your current location
CWD /samples/2/3/4/23414
550 Can't change directory to /samples/2/3/4/23414: No such file or directory
PWD
257 "/" is your current location
CWD /samples/2/3/4
250 OK. Current directory is /samples/2/3/4
CWD /
250 OK. Current directory is /
PWD
257 "/" is your current location
CWD /samples/2/3/4/23414
550 Can't change directory to /samples/2/3/4/23414: No such file or directory
MKD /samples/2/3/4/23414
257 "/samples/2/3/4/23414" : The directory was successfully created
MKD /samples/2/3/4/23414
550 Can't create directory: File exists
Hack: Duplicate Folder Creation
Thanks again. And great FTP library

Jan 23, 2013 at 10:01 PM

I was looking back over the code again and I see where such a problem could potentially happen if the GetFtpDirectoryName() extension method were malfunctioning. That method is an extension of the string type for working with FTP paths. So what I've done is added some extended debugging to CreateDirectory() which will hopefully give us an idea of what's going on behind the scenes. If you don't mind get the latest revisions which should print out the extra info I mentioned around the MKD commands to the server. 

Jan 23, 2013 at 10:03 PM

Another option is to set a break point on the following line (2472) in FtpClient.CreateDirectory() and step through to see what's happening internally:

 if (force && !DirectoryExists(path.GetFtpDirectoryName())) {

Jan 23, 2013 at 10:23 PM

Here's the log output using the latest commit 

 

211 End.
OPTS UTF8 ON
200 OK, UTF-8 enabled
PWD
257 "/" is your current location
CWD /samples/2/3/2/23287
550 Can't change directory to /samples/2/3/2/23287: No such file or directory
--Creating folder: /samples/2/3/2/23287/
PWD
257 "/" is your current location
CWD /samples/2/3/2/23287
550 Can't change directory to /samples/2/3/2/23287: No such file or directory
CreateDirectory("/samples/2/3/2/23287/", True): Create non-existent parent: /samples/2/3/2/23287
PWD
257 "/" is your current location
CWD /samples/2/3/2
550 Can't change directory to /samples/2/3/2: No such file or directory
CreateDirectory("/samples/2/3/2/23287", True): Create non-existent parent: /samples/2/3/2
PWD
257 "/" is your current location
CWD /samples/2/3
250 OK. Current directory is /samples/2/3
CWD /
250 OK. Current directory is /
PWD
257 "/" is your current location
CWD /samples/2/3/2
550 Can't change directory to /samples/2/3/2: No such file or directory
CreateDirectory("/samples/2/3/2", True)
MKD /samples/2/3/2
257 "/samples/2/3/2" : The directory was successfully created
CreateDirectory("/samples/2/3/2/23287", True)
MKD /samples/2/3/2/23287
257 "/samples/2/3/2/23287" : The directory was successfully created
CreateDirectory("/samples/2/3/2/23287", True)
MKD /samples/2/3/2/23287
550 Can't create directory: File exists
--Hack: Duplicate Folder Creation

I will also try seeing what it does at that break point

 

Jan 24, 2013 at 1:40 AM

I see the problem I believe, notice in this line:

CreateDirectory("/samples/2/3/2/23287/", True): Create non-existent parent: /samples/2/3/2/23287
The parent directory is the same as parameter you passed to CreateDirectory() minus the last slash. This is indeed a bug which I'll try to address tomorrow. In the mean time trimming off the trailing slash, i.e., path.TrimEnd('/'), will probably clear up the exception you're catching to work around this issue.

Jan 24, 2013 at 1:42 AM

Or more precisely:

_ftpConn.CreateDirectory(folder.TrimEnd('/'), true);

Jan 24, 2013 at 1:53 AM

I've reproduced the bug and it was such a simple fix I went ahead and pushed up a new revision that addresses the problem. The latest code should clear this up for you.

Jan 24, 2013 at 6:18 PM

great to hear, and thanks for all the help.

Jan 24, 2013 at 6:20 PM

Not a problem