Renaming a file with wildcard usage

0 votes
asked Nov 13, 2013 by chewdoggie (120 points)
edited Nov 14, 2013

Hello,

We used to be running version 3854, and have since upgraded to v4700 and then v4981 recently.

The following download scenario worked in 3854, but doesn't work in 4981.

We have a file that we have to download from an FTP server. We know the file begins with "997" and ends with ".txt" (99723445.txt or 99777333232.txt, e.g.), but we don't know anything more about the file name, except that there is only ONE file in the target directory that matches this pattern (clean up in this directory is done nightly). We want to download this file and rename it as "997_YYYYMMDD.txt", where YYYY is a 4-digit year, MM is a 2-digit month and DD is a 2-digit day. We have the logic in place to correctly rename the file.

Remote file specification:   997*.txt
Local file specification:    \\ServerName\folder1\folder2\folder3\997\99720131112.txt
Remote directory changed to: /Download

As I said, this used to work but the latest version throws an error stating, "Target path is not a directory". FTP seems to assume that this is going to match more than one file and sees a filename specified in the local directory and coughs up this error.

Is there anyway to get this to work with a simple getfile method ?

Applies to: Rebex FTP/SSL

1 Answer

0 votes
answered Nov 14, 2013 by Jan Sotola (16,540 points)
edited Nov 14, 2013

I'm sorry, but it is not clear for me, why it was working using the version 3854, while it is not working now. Actually, I cannot simply imagine, how could it ever work. Maybe, I don't understand you situation right.

I expect you were using the GetFiles method in the old version. The problem is that the GetFiles method (or the newer Download method) are intended for multiple-files operations. That's why they require the target path to be a directory, not a file-path. These methods do not supports file renaming as well.

Could you, please, send me a piece of code you are using for the file download (including the code using the old version). Plus alternatively a debug log (according to this instruction) would help.

I can suggest two possible solutions (in your situation, I'd recommend you the first one):

A) Find the exact filename on the FTP server using the GetList method and then download the single file using the GetFile method.

var lstAll = ftp.GetList();
var lst = lstAll.GetFiles("977*.txt");
if (lst.Length != 1)
    throw new Exception("Exactly one file expected.");

ftp.GetFile(lst[0], @"c:\y\newname.txt");

If your FTP server supports wildcards in the GetList method, you can speed up the algorithm with filtering on server side:

// caution: Not all FTP servers support wildcards in the GetList argument
var lst = ftp.GetList("997*.txt");
if (lst.Count != 1)
    throw new Exception("Exactly one file expected.");

ftp.GetFile(lst[0].Name, @"\\servername\folder\newname.txt");

B) Use the Download method and rename the file after downloading.

To find out the exact filename, you can use TransferProgressChanged event:

// register an event handler
ftp.TransferProgressChanged += ftp_TransferProgressChanged;

// download all files (expecting there is the only one)
ftp.Download("997*.txt", @"\\servername\folder");

// rename the file using the filename stored by the event handler
File.Move(@"\\servername\folder\" + lastFileName, @"\\servername\folder\newname.txt");

You will need the following member variable to store a filename of the transferred file (since we are sure there is only one filename to transfer, a scalar string variable is enough):

string lastFileName;

Add the following event handler to store the filename :

void ftp_TransferProgressChanged(object sender, FtpTransferProgressChangedEventArgs e)
{
    if (e.Action == TransferAction.Downloading && e.SourceItem.IsFile)
        lastFileName = e.SourceItem.Name;
}
...