This project is read-only.

Moving files on the FTP that have very long paths and/or invalid Windows characters in the path

May 16, 2014 at 12:32 PM
Hi.

The FTP server I'm connecting to with FtpClient is using a file system that supports longer paths than Windows does, and also support some characters that Windows deems as illegal.

I have code that checks if a given file is within Windows' limits (both path length and illegal characters). If this code says a file cannot be transferred to the Windows-box, I'd like to move this file to another path on the FTP.

The problem occurs when trying to call methods like CreateDirectory() and Rename() -- I'm getting exceptions like PathTooLongException, even though the path is valid on the FTP-site in question.

Has anyone found a good workaround to a problem like this?
Coordinator
May 16, 2014 at 1:45 PM
Edited May 16, 2014 at 1:47 PM
Please post the full transaction log with the failure. See the Debug.cs example for more information. Stack trace included so I can see if it's one of the internal path methods that's possibly failing.
May 16, 2014 at 2:21 PM
I think it's the internal path method that's failing:
The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
--------------
System.IO.PathTooLongException: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
   at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
   at System.IO.Path.GetDirectoryName(String path)
   at System.Net.FtpClient.FtpExtensions.GetFtpDirectoryName(String path)
   at System.Net.FtpClient.FtpClient.CreateDirectory(String path, Boolean force)
   at System.Net.FtpClient.FtpClient.CreateDirectory(String path)
Trasaction log of the file in question:
CWD /home/sigurdhj/errors/16.05.2014/asdasd/asd asd asd aa asd/Kooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo::asdasd
550 /home/sigurdhj/errors/16.05.2014/asdasd/asd asd asd aa asd/Kooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo::asdasd: No such file or directory
Coordinator
May 16, 2014 at 3:02 PM
The latest revision under the source tab on this site should work with arbitrary length path names and any characters. I've removed the use of System.IO.Path in the extensions used for cleaning up and parsing path names. Let me know if it works for you (worked with the path above in my tests).
May 16, 2014 at 4:24 PM
I've tried the latest source code and I'm now getting FtpCommandExceptions saying "No such file or directory" from my recursive directory listing method. Relevant part of my listing method:
private void GetListingRecursively(string fromFolder)
{
var items = _client.GetListing(fromFolder);
            foreach (var item in items)
            {
                switch (item.Type)
                {
                    case FtpFileSystemObjectType.Directory:
                        GetListingRecursively(item.FullName);
                        break;
It starts out with a parameter with the string "/home/sigurdhj/folder 1/folder 2/". On the second (first recursive) call it gets passed the item.FullName which is ".//home/sigurdhj/folder 1/folder2/folder 3". When trying to do a GetListing() call with a path starting with "./" things seem to go bad.

I don't think the "./" was a part of the item.FullName before -- might this be the problem?
Coordinator
May 16, 2014 at 4:33 PM
I just reverted a change that might be the cause of that. Please try to the latest revision.
May 16, 2014 at 4:43 PM
Seems to be working now going by my initial test. I'll keep testing over the weekend.

Thanks. :)
Coordinator
May 16, 2014 at 5:02 PM
No problem, have a good weekend.
May 18, 2014 at 4:49 PM
Edited May 18, 2014 at 4:55 PM
I've ran into a related problem with these long filenames. When trying to run my program on a machine that has Symantec Endpoint Protection (SEP) enabled, SEP's network intrusion prevention system won't allow any files with long filenames to be read. The BaseStream.Write() call in follow code from FtpSocketStream.cs throws an IOException:
public override void Write(byte[] buffer, int offset, int count) {
            if (BaseStream == null)
                return;

            BaseStream.Write(buffer, offset, count);
            m_lastActivity = DateTime.Now;
        }
Stack trace:
System.IO.IOException: Unable to write data to the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.FtpClient.FtpSocketStream.Write(Byte[] buffer, Int32 offset, Int32 count)
SEP error message: http://www.symantec.com/security_response/attacksignatures/detail.jsp?asid=20903

Is there any way around this except disabling SEP or editing it's policies?
Coordinator
May 19, 2014 at 1:05 AM
No, there is nothing I can do to work around SEP's restrictions.