我目前正面临一个关于QFtp的奇怪问题。我想从FTP服务器下载一堆文件,但当我在y上下载x个文件后,ftp->get()
命令完成,文件被填充,但没有SIGNAL
commandFinished()
的发射,因此它不会下载其他文件。
这是我的代码:
void Ftp::commandFinished(int i, bool error)
{
if(ftp->currentCommand() == QFtp::Get)
{
if(error)
{
//blablabla-ERROR-blablabla
}
currentFile->close();
filesToDownload.pop_front();
processFileList();
}
/**Gestion de la commande Login (authentification de l'utilisateur)
*/
if(ftp->currentCommand() == QFtp::Login)
{//not utile here}
/**Gestion de la commande ConnectToHost (connexion au serveur)
*/
if (ftp->currentCommand() == QFtp::ConnectToHost)
{//not utile here}
/**Gestion de la commande List (téléchargement d'un fichier)
*/
if(ftp->currentCommand() == QFtp::List)
{
if(error)
{
//Nananana-FAIL-nanana
}
//!Tri des fichiers à télécharger en fonction de leur dernière date de modification
if (!filesToDownload.isEmpty())
{
currentPeripheral->setLastDownloadDate(newLastModifiedDate) ;
std::sort(filesToDownload.begin(),filesToDownload.end(),compareQUrlInfos);
processFileList();
}
}
}
void Ftp::processFileList()
{
QUrlInfo info;
if (filesToDownload.isEmpty())
{
//!Suicide de l'instance de Ftp
ftp->close();
disconnect(this,0,0,0);
this->deleteLater();
return ;
}
info = filesToDownload.first();
QDir dlDir(QString::number(currentPeripheral->getId()));
//!Si un fichier a été téléchargé, on déclenche son traitement
if (currentFile != nullptr)
{
emit(oneDownloadFinished(currentFile->fileName(),currentPeripheral));
delete currentFile;
currentFile = nullptr;
}
//!On crée un répertoire de téléchargement si nécessaire
if (!dlDir.exists())
{
dlDir.mkdir(".");
}
//!on crée le fichier qui contiendra le téléchargement
currentFile = new QFile(dlDir.filePath(info.name()));
if(!currentFile->open(QIODevice::WriteOnly))
{
delete currentFile;
currentFile = nullptr;
emit(writeToMonitoringConsole(QString("Erreur lors de la creation du fichier "+info.name()),"Error"));
return;
}
//Here I start (sometimes) a never ending fail
ftp->get(info.name(), currentFile);
}
起初,我以为是因为我提出了太多的请求,因此被拒绝了,但即使使用Sleep(2000)
,它也会阻止。阻塞出现得更快。我通常可以下载大约30个文件(幸运的时候是70个,曾经我有200个!(。使用Sleep(2000)
,我几乎无法成功下载2-3个文件。
这是我的错误吗?我没有发现QFtp有限制吗?还是别的什么?
EDIT:发布后,我测试了一些东西,在监控dataTransferProgress((信号时,令人震惊的是,有问题的文件已完全下载(qDebug说"88928/88928"(,但我从未输入commandFinished((。
我的插槽commandFinished((链接到我的QFtp::commandFinish SIGNAL方式:
connect(ftp, SIGNAL(commandFinished(int,bool)), this, SLOT(commandFinished(int,bool)));
我看到了几乎相同的情况,我使用的FTPWidget
类从未接收到GET请求的commandFinished
。dataTransferProgress((信号可靠地报告100%下载及其全部内容。
我已经破解了使用设置超时如下:
// Set up a single shot QTimer and connect it to a function to fix things
connect(m_lostFinishedTimer, SIGNAL(timeout()), this, SLOT(lostFinishedHack()));
// Start the timeout when the download data progress hits 100%
void FtpWidget::updateXferProgress(qint64 readBytes, qint64 totalBytes)
{
m_progressBar->setValue(progress_value(readBytes, totalBytes));
if (m_downloading && readBytes == totalBytes)
m_lostFinishedTimer->start();
}
// And don't forget to stop the timer if you do get a finish:
void FtpWidget::commandFinished(int id, bool error)
{
QFtp::Command cmd = m_ftp->currentCommand();
// ...
if (cmd == QFtp::Get)
{
m_lostFinishedTimer->stop();
//....
}
// ...
}
计时器连接到修复程序时,基本上关闭下载文件,重新连接服务器,然后转到下一个文件
void FtpWidget::lostFinishedHack()
{
if (!m_downloading)
return;
if (m_downloadFile)
{
DOUT("FtpWidget::lostFinshedHack() -- file: " << DS(m_downloadFile->fileName()) << "n");
m_downloadFile->close();
delete m_downloadFile;
m_downloadFile = 0;
}
// just reconnect the thing
Connect(m_ftpServerName->text());
downloadNextFile();
}
这似乎已经足够好了,尽管我使用了一个相当大的超时。
所以,在我把这项工作做好一段时间后,我回去看看QFtp内部发生了什么。使用调试器在断点上添加打印命令,我可以看到来自的原始回复。似乎发生的事情是,我使用的ftp服务器有时会以不同的顺序发送ftp回复。
当它工作时,我的轨迹看起来像:
FtpWidget::commandStarted(id: 265) -- Get
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 200, text "Operation successful"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 213, text "135980"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 200, text "Operation successful"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 150, text "Opening BINARY connection for 000-23Sep2014_103527.jpg (135980 bytes)"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 226, text "Operation successful"
FtpWidget::commandFinished(id: 265, error: 0) -- Get
其中FtpWidget::commandStarted
和commandFinished
是我的插槽,_q_piFtpReply((是QFtp对象的私有部分,我在其中挂起了跟踪断点。
当它失败时,我得到:
FtpWidget::commandStarted(id: 256) -- Get
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 200, text "Operation successful"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 213, text "135896"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 200, text "Operation successful"
Function: QFtpPrivate::_q_piFtpReply(int, const QString &), code: 150, text "Opening BINARY connection for 000-23Sep2014_103525.jpg (135896 bytes)"
FtpWidget::lostFinshedHack()
FtpWidget::lostFinshedHack() -- file: C:/Users/sean/Temp/Snapshots5/000-23Sep2014_103525.jpg
FtpWidget::connect("ftp://root@169.254.1.180/")
在200个回复代码之后获得150个回复代码似乎是个问题。因此,如果你去查找FTP回复代码并查看qftp.cpp,那么在150导致qftp实现状态机进入永久等待之后,150就会到达。据我所知,是我的ftp服务器把事情搞砸了,而不是qftp.cpp(也许我应该试试wireshark来确定(。
目前,我坚持我的超时解决方法来解决这个问题。
我来不及回复,但它仍然可能帮助其他人。
在CCD_ 10中,检查CCD_,因为如果您的最后一个命令是get
,并且当调用commandFinished()
插槽时if (ftp->currentCommand() == QFtp::Get)
将无法识别最后一个命令,因为您当前的命令可能不是get
,因为它已经完成。
您也可以使用id进行检查作为if(ftp->currentCommand() == QFtp::Get || 1 == id)