QFtp Get никогда не запускает commandFinished()

В настоящее время я сталкиваюсь со странной проблемой, связанной с QFtp. Я хочу загрузить кучу файлов с FTP-сервера, но когда я подхожу к какому-то моменту, после загрузки x-файлов на y, ftp->get() Команда выполнена, файл заполнен, но нет выброса SIGNALcommandFinished() и, таким образом, он не загружает другие файлы.

Вот мой код:

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, которое я не нашел? Или что-то другое?

РЕДАКТИРОВАТЬ: Я протестировал некоторые вещи с тех пор, как я их опубликовал, и при мониторинге сигнала dataTransferProgress() было замечательно, что проблемный файл полностью загружен (qDebug говорит "88928/88928"), но я никогда не ввожу commandFinished().

Мой слот commandFinished () связан с моим QFtp::commandFinished SIGNAL следующим образом:

connect(ftp, SIGNAL(commandFinished(int,bool)), this, SLOT(commandFinished(int,bool)));

2 ответа

Я вижу почти то же самое, с FTPWidget класс я использую никогда не получая commandFinished для запроса GET. Сигнал 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/")

Получение кода ответа 150 после кода ответа 200, похоже, является проблемой. Поэтому, если вы посмотрите на коды ответов FTP и просмотрите qftp.cpp, вы увидите, что 150 прибывает после того, как 150 заставляет конечный автомат реализации qftp переходить в постоянное ожидание. Насколько я могу сказать, это мой ftp-сервер, который все портит, а не qftp.cpp (может быть, я должен попробовать Wire Shark, чтобы убедиться).

Пока я придерживаюсь своего временного решения проблемы.

Я слишком поздно отвечаю, но это может помочь другим.

В void Ftp::commandFinished(int i, bool error) всегда лучше проверить QFtp::None вариант также, так как если ваша последняя команда get и когда commandFinished() слот вызывается тогда if (ftp->currentCommand() == QFtp::Get) не сможет определить последнюю команду, так как ваша текущая команда не может быть get потому что это уже закончено.

Вы также можете проверить с идентификатором как if(ftp->currentCommand() == QFtp::Get || 1 == id)

Другие вопросы по тегам