PDA

View Full Version : QFtp report error



Carmengg
3rd February 2014, 12:38
Hi everyone.

I want to upload a file and sometimes this "upload" doesn't work fine. I have tried to catch the error but I haven't succeeded.I just need that when the file doesn't upload the function upload returns FALSE.

That is my code


void FileUploader::ftpCommandFinished(int id, bool error){
if (myUploader->currentCommand() == QFtp::ConnectToHost) {
if (error){
printf("upload file resume ERROR: %s\n",myUploader->errorString().toAscii().data());
myUploader->abort();
myUploader->deleteLater();
myUploader = 0;
return;
}else
//if (id == login)
myFile->remove("data/Tests/" + m_fileName +".csv");
/*else if (id == connectToHost)
printf("connectToHost finished\n");
else if (id == get)
printf("get finished\n");*/
}else if (myUploader->currentCommand() == QFtp::Login){
if (error){
printf("upload file resume ERROR: %s\n",myUploader->errorString().toAscii().data());
myUploader->abort();
myUploader->deleteLater();
myUploader = 0;
return;
}else
//if (id == login)
myFile->remove("data/Tests/" + m_fileName +".csv");
}else if (myUploader->currentCommand() == QFtp::Put){
if (error){
printf("upload file resume ERROR: %s\n",myUploader->errorString().toAscii().data());
myUploader->abort();
myUploader->deleteLater();
myUploader = 0;
return;
}else
//if (id == login)
myFile->remove("data/Tests/" + m_fileName +".csv");
}
}

bool FileUploader::upload(QString fileName,accountInfoSettings* myAccountInfoSettings){

myUploader = new QFtp();
/*bool error = FileUploader::zip(fileName);
if(!error){

printf("error del bueno\n");
fflush(stdout);
}

printf("Zip file created\n");
fflush(stdout);*/

myFile = new QFile("data/Tests/" +fileName); //.remove(".csv")+".zip");

m_fileName = fileName;
myFile->open(QFile::ReadOnly);
connect(myUploader, SIGNAL(commandFinished(int,bool)), this, SLOT(ftpCommandFinished(int,bool)));
/*myUploader->connectToHost("www.at4wireless.com",21); myUploader->login("demo_at4","H3mEwwUC");*/
myUploader->connectToHost(myAccountInfoSettings->getUrl(),21);
myUploader->login(myAccountInfoSettings->getUser(),myAccountInfoSettings->getPassword());
myUploader->put(myFile,fileName);
printf("Put\n"); fflush(stdout);

if (QFtp::UnknownError == myUploader->error() || QFtp::HostNotFound == myUploader->error() ||
QFtp::ConnectionRefused == myUploader->error() || QFtp::NotConnected == myUploader->error())
return false;
else return true;
}


Any help is welcome :)

Thanks again, Carmen.

anda_skoa
3rd February 2014, 14:32
QFtp works asynchronously, so it hasn't started working yet when you check before returning.

Most methods to fake blocking behavior have unwanted side effects, so the best way would be not to rely on that but start the upload and get its result via signal.

Which version of Qt are we talking about here, btw?

Cheers,
_

Carmengg
4th February 2014, 08:20
Hi. Firstly thank you to answer me :)

I'm not sure about it but I think that the Qt version is 4.8.

I have tried too that:



void FileUploader::ftpCommandFinished(int id, bool error){
if (error){
printf("upload file resume ERROR: %s\n",myUploader->errorString().toAscii().data());
myUploader->abort();
myUploader->deleteLater();
myUploader = 0;
return;
}else
myFile->remove("data/Tests/" + m_fileName +".csv");
}

bool FileUploader::upload(QString fileName,accountInfoSettings* myAccountInfoSettings){

myUploader = new QFtp();

myFile = new QFile("data/Tests/" +fileName); //.remove(".csv")+".zip");

m_fileName = fileName;
myFile->open(QFile::ReadOnly);
connect(myUploader, SIGNAL(commandFinished(int,bool)), this, SLOT(ftpCommandFinished(int,bool)));

if (QFtp::UnknownError == myUploader->error() || QFtp::HostNotFound == myUploader->error() ||
QFtp::ConnectionRefused == myUploader->error() || QFtp::NotConnected == myUploader->error())
return false;
myUploader->connectToHost(myAccountInfoSettings->getUrl(),21);
if (QFtp::UnknownError == myUploader->error() || QFtp::HostNotFound == myUploader->error() ||
QFtp::ConnectionRefused == myUploader->error() || QFtp::NotConnected == myUploader->error())
return false;
myUploader->login(myAccountInfoSettings->getUser(),myAccountInfoSettings->getPassword());
if (QFtp::UnknownError == myUploader->error() || QFtp::HostNotFound == myUploader->error() ||
QFtp::ConnectionRefused == myUploader->error() || QFtp::NotConnected == myUploader->error())
return false;
myUploader->put(myFile,fileName);
printf("Put\n"); fflush(stdout);

if (QFtp::UnknownError == myUploader->error() || QFtp::HostNotFound == myUploader->error() ||
QFtp::ConnectionRefused == myUploader->error() || QFtp::NotConnected == myUploader->error())
return false;
else return true;
}



And it didn't work either.

anda_skoa
4th February 2014, 09:45
I'll try to explain that a bit better:

When you do any of the QFtp commands, e.g.


myUploader->connectToHost(...)

they will return immediately with an identifier value for that operation. The operation itself is executed asynchronously, its result is signalled via commandFinished().
So checking an error code or state right after the call is more or less without meaning (will return the state of the QFtp class at that time, not related to the new operation at all).

What you have here is a sequence of such operations being scheduled for execution, they will be executed after you return from upload().

If you want to know when the put operation has finished, you need to remember the operation identifier returned by put() and when that id comes along in ftpCommandFinished() then you are done.
E.g. you can then emit your own signal delete the file and ftp instances, etc.

Cheers,
_

Carmengg
4th February 2014, 11:50
Sorry. I'm still lost.

Could you give me a example with code?

Thanks

anda_skoa
4th February 2014, 12:27
Which part is it that you have a problem with?

Storing the request id?



void FileUploader::upload(QString fileName,accountInfoSettings* myAccountInfoSettings){

myUploader = new QFtp();
connect(myUploader, SIGNAL(commandFinished(int,bool)), this, SLOT(ftpCommandFinished(int,bool)));

myFile = new QFile("data/Tests/" +fileName); //.remove(".csv")+".zip");

m_fileName = fileName;
myFile->open(QFile::ReadOnly);

myUploader->connectToHost(myAccountInfoSettings->getUrl(),21);
myUploader->login(myAccountInfoSettings->getUser(),myAccountInfoSettings->getPassword());

m_uploadId = myUploader->put(myFile,fileName); // remember ID of upload operation
}

Or checking the ID?


void FileUploader::ftpCommandFinished(int id, bool error){
if (error){
printf("upload file resume ERROR: %s\n",myUploader->errorString().toAscii().data());
myUploader->abort();
}else if (id == m_uploadId) // upload operation finished
myFile->remove("data/Tests/" + m_fileName +".csv");

myUploader->deleteLater();
myUploader = 0;

delete myFile;
myFile = 0;
}

Carmengg
4th February 2014, 12:45
Well.
I need to know if any of this operations has finished succesfull.
connnectToHost, login, put
If something wrong happend the function "FileUploader" has to return false and then my app says that the file has not been uploaded. Untill now each time my app try to upload a file says that file has been uploaded correctly but it's not true. For example sometimes I have not wifi signal

I do not care which of them has missed. If any functions didn't work I only need to know that as a result the file didn't upload.

anda_skoa
4th February 2014, 13:33
Your options are one signal carrying a state information or two signal

Fo example one signal with state:


void FileUploader::ftpCommandFinished(int id, bool error){
if (error){
printf("upload file resume ERROR: %s\n",myUploader->errorString().toAscii().data());
myUploader->abort();
emit finished(false);
}else if (id == m_uploadId){ // upload operation finished
myFile->remove("data/Tests/" + m_fileName +".csv");
emit finished(true);
}

myUploader->deleteLater();
myUploader = 0;

delete myFile;
myFile = 0;
}




FileUploader *uploader = new FileUploader(this);
connect(uploader, SIGNAL(finished(bool)), this, SLOT(onUploadFinished(bool)));

uploader->upload(...);



void SomeClass::onUploadFinished(bool success)
{
FileUploader *uploader = qobject_cast<FileUploader*>(sender());

// react on success

uploader->deleteLater();
}


You can of course re-use the same uploader instance, have the filename in the signal, etc.

Alternatively you could look at QNetworkAccessManage::put()

Cheers,
_