PDA

View Full Version : QFtp: downloading a whole folder from a remote server.



balazsbela
3rd August 2007, 12:20
So I managed to write a function to upload a whole folder to an ftp server, here is the code if anyone is searching this forum (like I did) in hope of finding a function like this:



void sendFolder(const QString &path,const QString &dirPath)
{
QTextStream cout(stdout, QIODevice::WriteOnly);
QFileInfo fileInfo(path);
if (fileInfo.isDir())
{
QString dirName = path;
dirName.remove(0,dirPath.size());
ftp->mkdir(dirName);
QDir dir(path);
QStringList entries = dir.entryList(QDir::AllEntries|QDir::NoDotAndDotDo t,QDir::DirsFirst);
foreach (QString entry, entries)
{
sendFolder(dir.filePath(entry),dirPath);
}
}
else
{
QFile *file = new QFile(path);
if(file->open(QIODevice::ReadOnly))
{
QString filename =path;
filename.remove(0,dirPath.size());
ftp->put(file,filename);
file->close();
}
else cout <<"Could not open file:"<<path<<"\n";
}
}


The dirPath parameter contains the path to the local directory that contains the folder you want to upload.
If the directory you are trying to upload is: /home/user/mydir then dirPath should be /home/user/
Because the dirPath substring will be removed to create the directory mydir on the server.

Ok.
So now that I've got that working, I am trying to figure out how to download a whole folder from a remote ftp server into a local folder.
If anyone has some code that does that I would be very grateful to have it.
I searched this forum but couldn't find what I need.
Also the qt4 ftp example doesn't contain downloading a whole folder, only files.

Can anyone help me ?
Thanks.

daracne
3rd August 2007, 23:32
I'll look around and see if I can find the code I wrote to do this, however I can tell you that my implementation used two member functions in QFtp.

QFtp::list()
signal QFtp::listInfo(const QUrlInfo& i)

balazsbela
4th August 2007, 00:07
I started writing one using those two.
It would be great if you could find it.
It is getting late, I think I'll continue to write that tomorrow.
Thanks for replying.

balazsbela
4th August 2007, 11:19
So if I'm right this should list all folders and files(even in subfolders) in the folder I want to download.

Here is the code:



void getFolder(QString path)
{
ftp->list(path);
connect(ftp,SIGNAL(listInfo(QUrlInfo)),this,SLOT(p rocessFolder(QUrlInfo)));
}

void processFolder(const QUrlInfo &i)
{
QTextStream cout(stdout, QIODevice::WriteOnly);
if (i.isDir())
{
cout <<"Directory:"<< i.name()<<"\n";
ftp->list(i.name());
}
else
{
cout <<"File:"<<i.name()<<"\n";
}
}


Unfortunately it doesn't.
It lists all files for one subfolder but not for every subfolder.
Why? What am I doing wrong ?

Is there any way to tell QFtp -> list() to list folders first ?
Like in
QDir::DirsFirst .
Also I would like to list them as /subfolder/file or /subfolder/subfolder/file but QUrlInfo doesn't have a function to return the path to a file.
Is there any way to convert it to QUrl?
Any help is appreciated.

jacek
5th August 2007, 00:39
So if I'm right this should list all folders and files(even in subfolders) in the folder I want to download.
[...]
Unfortunately it doesn't.
The problem is that you don't change the current directory.

Try something like:


void getFolder(QString path)
{
pendingPaths.append( path );
connect(ftp,SIGNAL(listInfo(QUrlInfo)),this,SLOT(p rocessFolder(QUrlInfo)));
connect(ftp,SIGNAL(commandStarted(int)),this,SLOT( commandStarted(int)));
ftp->list(path);
}

void processFolder(const QUrlInfo &i)
{
QTextStream cout(stdout, QIODevice::WriteOnly);
if (i.isDir())
{
cout <<"Directory:"<< i.name()<<"\n";
QString dir = currentPath + QDir::separator() + i.name();
pendingPaths.append( dir );
ftp->list( dir );
}
...
}

void commandStarted( int id )
{
Q_UNUSED( id );
if( ftp->currentCommand() == QFtp::List ) {
currentPath = pendingPaths.first();
pendingPaths.removeFirst();
}
}

balazsbela
5th August 2007, 09:34
Nevermind I got it working, but it was a lot more complicated:
Here is the code:



void qOrganizer::getFolder(QString path,QString localPath)
{
QTextStream cout(stdout, QIODevice::WriteOnly);
QDir localDir(localPath);
listCommandVector.append(ftp->list(path));
stack.push(path);
localDir.mkdir(path);
connect(ftp,SIGNAL(listInfo(QUrlInfo)),this,SLOT(p rocessFolder(QUrlInfo)));
connect(ftp,SIGNAL(commandFinished(int,bool)),this ,SLOT(processCommand(int,bool)));
ftpEntryes = new QStringList;
lpath=localPath;
}

void qOrganizer::processFolder(const QUrlInfo &i)
{
if(i.isDir())
{
entryList.push_front(i);
}
else
if(i.isFile())
entryList.push_back(i);
}

static int nrcomfin=0;
void qOrganizer::processCommand(int com,bool err)
{
nrcomfin++;
QString path;
QTextStream cout(stdout, QIODevice::WriteOnly);
bool containsSubfolders=0;
bool entryExists=0;
QDir localDir(lpath);

if(listCommandVector.indexOf(com)!=-1)
{
path = stack.top();
foreach(QUrlInfo entry,entryList)
{
if((entry.isFile())&&(listedFiles.indexOf(entry)==-1))
{
QString foldPath = path+"/"+entry.name();
ftpEntryes->append(foldPath);
listedFiles.append(entry);
cout <<"File:"<<foldPath<<"\n";
entryExists=1;
}
else
if((entry.isDir())&&(listedFolders.indexOf(entry)==-1))
{
QString foldPath = path+"/"+entry.name();
// cout <<"Folder:"<<foldPath<<"\n";
stack.push(foldPath);
localDir.mkdir(foldPath);
// cout << stack.top() <<"\n";
listCommandVector.append(ftp->list(foldPath));
listedFolders.append(entry);
containsSubfolders=1;
entryExists=1;
break;
}
}
if((stack.size()>1)&&(nrcomfin%2!=0)) stack.pop();
entryList.clear();
//cout << stack.size() << stack.top() <<" "<<nrcomfin<<"\n";
if((!containsSubfolders)&&(entryExists))
listCommandVector.append(ftp->list(stack.top()));
if((!containsSubfolders) && (!entryExists)) downloadFiles();
}
else
if(getCommandVector.indexOf(com)!=-1)
{
ftpFile=fileQueue.dequeue();
ftpFile-> close();
cout <<"Completed:"<<ftpFile->fileName()<<" "<<"Errors:"<<err<<"\n";
ftpFile->deleteLater();
};
}

void qOrganizer::downloadFiles()
{
QTextStream cout(stdout, QIODevice::WriteOnly);
cout <<"Downloading"<<"\n";
foreach(QString entry,*ftpEntryes)
{
QFile *file = new QFile(lpath+entry);
cout << "get " << entry <<" "<<lpath+entry<<"\n";
fileQueue.enqueue(file);
file->open(QIODevice::WriteOnly);
getCommandVector.append(ftp -> get(entry,file));
}
}


Not too pretty but it works! :)