I have implemented the following code to download files from an FTP server that are inside folders and subfolders.
void TFAct::Download()
{
try
{
Ftp->ChangeDir("/");
//Actualizo//
NewDats(CTemp);
}
catch (...)
{
}
}
void TTFAct::::NewDats(AnsiString Path)
{
std::auto_ptr<TStringList> Elementos (new TStringList);
Ftp->List(Elementos.get());
int NumElemnt = Ftp->DirectoryListing->Count;
int Pos;
bool *IsDir = new bool[NumElemnt];
for (int i=0;i<NumElemnt;i++)
{
TIdFTPListItem* ListItem = Ftp->DirectoryListing->Items[i];
Elementos->Strings[i] = ListItem->FileName;
FechAlla[i] = ListItem->ModifiedDate;
IsDir[i]=ListItem->ItemType == ditDirectory;
}
for (int i=0;i<NumElemnt;i++)
{
//Si es una SubCarpeta
if(IsDir[i])
{
Ruta = Path + Elementos->Strings[i];
AnsiString Copia = Path + Elementos->Strings[i];
Folder = Ruta.SubString(Ruta.LastDelimiter("\")+1,Ruta.Length());
//Compruebo si el Directorio existe
if(DirectoryExists(Ruta))
{
Ftp->ChangeDir(Elementos->Strings[i]);
NewDats(Ruta + "/");
}
else
{
CreateDir(Ruta);
Ftp->ChangeDir(Elementos->Strings[i]);
NewDats(Ruta + "/");
}
}
else
{
try
{
Ftp->Get(Elementos->Strings[i],Copia,true); //bajo archivo
}
catch(...)
{
}
} //IsDir
}//for
Ftp->ChangeDirUp();
}
On Windows, it works perfectly.
An Android, it goes through folders and subfolders perfectly, but when it has to download files, sometimes it downloads all of the files, other times it downloads only some of the file, and other times it downloads none at all.
What could be the problem?
I see a lot of issues with this code:
you should not be using
AnsiStringat all on Android (or Windows, for that matter). UseUnicodeString(or better,System::String) instead. Both Operating Systems are Unicode-based, and you are using a Unicode-based version of C++Builder, and a Unicode-based version of Indy, so don't use ANSI strings at all.There is no point in passing a
TStringListintoTIdFTP::List()if you are going to ignore its output. So, you should pass innullptrand just useTIdFTP::DirectoryListingby itself.You are leaking your
IsDirarray. Usestd::vectorinstead ofnew[].When calling
Ruta.LastDelimiter("\"), you need to escape the\character using either"\\"orR"(\)". Or, you could simply useExtractFileName()instead of usingRuta.SubString()at all. However, you are also mixing\and/characters in your paths. Don't do that. Use/for FTP paths, and useSystem::Sysutils::PathDelimorSystem::Ioutils::TPath::DirectorySeparatorCharfor local filesystem paths. Don't use a singlestringto represent both kinds of paths, keep them separate.but most importantly, you are ignoring ALL possible errors. If Indy encounters an error, it will throw an exception, which you are catching and discarding. There are a number of reasons why an FTP server might reject access to a file/folder. Maybe you requested in invalid path. Maybe you don't have access to the path. Not only are you discarding all errors, but you are not even logging them anywhere, so you can't possibly know when an error has actually occurred, or what kind of error it was. Was it an ignorable error? Was it a fatal error? You don't know, so you aren't acting on it.