0 votes
by (1.1k points)
edited

Recently I changed a working Ftp.BeginPutFile call where I pass the local file name as a string, to a call of another overload of Ftp.BeginPutFile that gets a Stream object instead of the file name.

The reason is that I have to support paths that are longer than 260 characters for which your library (since it is based on the standard .NET functions) fails.

Instead, I am using my self-developed Long Path Library and create a FileStream object with that library and pass it to the Ftp.BeginPutFile overload.

When doing this, the upload often (but not always) fails with an InvalidOperationException:

Local item doesn't exist.

On the call stack:

at Rebex.IO.LocalItem.1z5Wy2Z()
at Rebex.IO.LocalItem.get_Length()
at 1RyBHn.27NpLhZ.zY1W4Z(TransferAction , String , String , Char[] )
at 1RyBHn.27NpLhZ.zY1W4Z(TransferAction , String , Stream , Char[] )
at Rebex.Net.Ftp.17h3LnZ(TransferAction , String , Stream )
at Rebex.Net.Ftp.BeginPutFile(Stream sourceStream, String remotePath, AsyncCallback callback, Object state)
bei ZetaProducerPublishing.Runtime.Protocols.FtpProtocol...

Actually the file being opened does exist.

My question is:

How to correctly use your library with a file stream instead of a file name?

Update 1, some more details:

My old code was:

...
var ar1 =
    _ftp.BeginPutFile(
        information1.LocalFilePath,
        information1.RemoteFolderPath.TrimEnd('/') + '/' +
        ZlpPathHelper.GetFileNameFromFilePath(information1.LocalFilePath),
        delegate {},
        null);
...

My new code is:

...
using (var sourceStream = new System.IO.FileStream(
    ZlpIOHelper.CreateFileHandle(
        information1.LocalFilePath,
        CreationDisposition.OpenExisting,
        FileAccess.GenericRead,
        FileShare.Read),
    System.IO.FileAccess.Read))
{
    var ar1 =
        _ftp.BeginPutFile(
            sourceStream,
            information1.RemoteFolderPath.TrimEnd('/') + '/' +
            ZlpPathHelper.GetFileNameFromFilePath(information1.LocalFilePath),
            delegate {},
            null);
    ...

The exception is thrown inside the BeginPutFile call.

Since I am using my long path library extensively in a lot of projects, I am assuming that it is working reliable. I can imagine that there is a special condition inside Rebex that I do not cover or an issue inside Rebex with streams.

Applies to: Rebex FTP/SSL

1 Answer

+1 vote
by (62.8k points)
edited
 
Best answer

It is an imperfection of the component. It cannot handle FileStream.Name properly if created from IntPrt.

I have just added a fix. It will be included in the next public release. I emailed you current hotfix version.

by (1.1k points)
edited

Thanks a lot, Lukas. I'll try immediately. Will this work for the SFTP and SCP counterparts, too?

by (62.8k points)
edited

Yes, the problem was located in a shared code. This should be solved in all Rebex components :-)

...