Файлы повреждаются при загрузке с помощью QNetworkAcessManager

Я разрабатываю клиентское приложение, целью которого является загрузка некоторых файлов с веб-сервера, временное сохранение их в папке Temp, проверка целостности файлов, а затем отправка их на FTP-сервер в устройстве Embedded Linux.

Недавно у меня возникли проблемы при выполнении процесса на этапе предварительной разработки, когда я пытался выполнить загрузку с моего локального компьютера (см. соответствующий вопрос здесь). Теперь я могу загружать и загружать без ошибок и с проверкой (я использую QCryptographicHash + размер файла для проверки любых несоответствий) со своей машины, но этого не происходит, когда я пытаюсь загрузить с HTTP-сервера.

Всего загружается 8 файлов: три .tar.gz, один простой текст, две программы и два бинарника. Я могу успешно загрузить все сжатые файлы, текстовый файл и один из двоичных файлов, но другие, а именно две программы и один из двоичных файлов (образ ядра Linux), всегда загружаются неправильно.

Я проверяю это, замечая не только то, что хэш возвращает ошибку для них, но и их размеры: их размеры всегда неверны (и всегда одно и то же ошибочное значение при любой попытке загрузки). И файлы на сервере все правильные.

Мое первое подозрение заключалось в том, что мне нужно настроить загрузку по HTTP таким образом, чтобы он отличался от обычной загрузки по FTP с локальной машины, но я не знаю, как это будет. Более того, если эта дополнительная конфигурация была необходима, то почему некоторые файлы всегда возвращаются правильно?

Вот соответствующий код на данный момент:

void MainWindow::processNextDownload()
{
    QUrl ulrTemp(updateData.at(transferStep).downloadUrl.arg(ui->leID->text()));    //"//" +

    if (updateData.at(transferStep).downloadUrl.contains("http"))
        ulrTemp.setScheme("http");
    else
        ulrTemp.setScheme("file");

//    ulrTemp.setUserName();
//    ulrTemp.setPassword();
//    ulrTemp.setPort();

    qDebug() << "Downloading" << transferStep << "from" << ulrTemp;

#if 1
    poReply = downloadNetworkManager->get(QNetworkRequest(ulrTemp));
#else
    QNetworkRequest request;
    request.setUrl(ulrTemp);
    request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");

    poReply = downloadNetworkManager->get(request);
#endif

    connect(poReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(slotDownloadProgress(qint64,qint64)));

    ui->statusBar->showMessage(tr("Downloading: %1").arg(updateData.at(transferStep).itemName));
}


void MainWindow::slotFileDownloaded(QNetworkReply* reply)
{
    if (reply && (reply->error() != QNetworkReply::NoError))
    {
        ui->statusBar->clearMessage();

        if (!isSingleFile)
        {
            const QString strTemp = tr("An error occurred while downloading \"%1\": %2 (error message: %3)")
                                    .arg(updateData.at(transferStep).downloadName).arg(reply->error()).arg(reply->errorString());

            QMessageBox::critical(this,tr("Error in download"),strTemp);
        }
        else
        {
            //irrelevant...
        }

        finished(false);

        return;
    }

    qDebug() << "To write: " << reply->bytesAvailable();

    QByteArray downloadedData = reply->readAll();

    reply->deleteLater();
    poReply->deleteLater();

    //![]
    static const QString tempFilePath = QDir::tempPath();

    if (!isSingleFile)
    {
        QFile file(tempFilePath + "/" + updateData.at(transferStep).downloadName);


        if (!file.open(QFile::WriteOnly | QFile::Truncate))
        {
            qDebug() << "Failure opening temp file to write: " << file.fileName();

            QMessageBox::critical(this,
                                  tr("Error"),
                                  tr("An error occured while trying to open a temporary file to write the downloaded data (file: %1).").arg(file.fileName()));

            transferStep = downloadStepCount;

            slotFileUploaded(NULL);

            return;
        }

        qint32 bytesWritten = file.write(downloadedData);
        file.flush();

        if (downloadedData.size() != bytesWritten)
            qDebug() << "Write failed, wrote" << bytesWritten << "out of" << downloadedData.size() << "bytes.";
        else
            qDebug() << "Wrote " << bytesWritten << "bytes.";


        file.close();

        //![]
        if (++transferStep >= downloadStepCount)
        {
            qDebug() << "Start hash check";
            slotStartHashCheck();

            return;
        }

        processNextDownload();
    }
    else
    {
        //irrelevant...
    }
}

И вот почему я получаю (последнее числовое значение после «=» в хеш-коде — это размер файла):

Сообщение об ошибке

Итак, что мне не хватает?


person Momergil    schedule 05.06.2015    source источник
comment
Я не вижу какой-либо немедленной ошибки, qint32 bytesWritten = file.write(downloadedData) может писать меньше, чем предполагалось, но когда вы сравните размеры, вы должны увидеть, не удастся ли это... Размеры на диске совпадают с размерами в Calculated..., я думаю ? Тогда код, вычисляющий хэши, также может иметь ошибки, но они должны отображаться независимо от локального или http-сервера... Я полагаю, загрузка файлов работает другими способами? Браузер, wget и т. д. Было бы также интересно узнать, является ли загруженный файл частичной загрузкой (соответствующей ожидаемому файлу, но усеченной) или он иным образом поврежден.   -  person Frank Osterfeld    schedule 05.06.2015
comment
@FrankOsterfeld Привет! Да, размеры файлов, рассчитанные Linux Ubuntu, соответствуют файлам во всех ситуациях: оригиналы с исходным размером (который появляется в ожидаемом хэш-коде) и загруженные файлы с неправильным размером (после расчета...). Так что ошибок в калькуляторе хэш-кода нет: везде использую одни и те же функции. Более того, даже если хэш был неправильным, размер файла все равно имеет проблемы; Я мог бы проверить это в одиночку.   -  person Momergil    schedule 05.06.2015
comment
@FrankOsterfeld Что касается браузера, это было интересно: загрузив Mozilla Firefox, я получил ТОЧНО такую ​​же ситуацию! (одни и те же файлы были правильными и такими же были неправильными). Насчет того, что он все еще действителен, это ничего не стоит: даже если файлы все еще как-то работают, мне нужно проверить их качество тем или иным способом, который не включает выполнение и просмотр :)   -  person Momergil    schedule 05.06.2015
comment
Конечно, но это была бы ценная информация для отладки того, что происходит не так. Но если Mozilla не работает так же, проблема, похоже, на стороне сервера?   -  person Frank Osterfeld    schedule 05.06.2015
comment
@FrankOsterfeld хороший звонок. Я провожу некоторые исследования в Интернете и вернусь позже с некоторыми обновлениями. Спасибо за помощь!   -  person Momergil    schedule 08.06.2015
comment
@FrankOsterfeld, кажется, я нашел проблему: взгляните на superuser.com/questions/925229/files-get-corrupted-when-downloaded-from-ftp-server . Теперь мне нужно узнать, как настроить QNetworkAcessManager для загрузки в двоичном виде, и проблема решена.   -  person Momergil    schedule 08.06.2015
comment
Звучит странно, что QNAM нужно адаптировать для этого. О каком типе контента сообщает сервер?   -  person Frank Osterfeld    schedule 08.06.2015
comment
@FrankOsterfeld, на самом деле это не так; моя ошибка. QNAM уже скачивает бинарники; по какой-то причине мое первоначальное тестирование с ним не удалось, поэтому я предположил, что он загружается с ASCII. (Но сервер ничего не сообщает, это нормально: я просто должен гарантировать, что файлы были загружены как двоичные файлы).   -  person Momergil    schedule 08.06.2015