2015-04-09 4 views
2

Я использую Qt's QNetworkAccessManager для загрузки файла из места (в настоящее время это локальный компьютер, но в будущем он будет HTTP-сервером) и временно сохраняет его в файле TEMP (linux убунт). Проблема, которую я обнаружил, заключается в том, что файл (исполняемый файл) поврежден в процессе: когда я пытаюсь запустить файл как исполняемый файл, он возвращает классическую ошибку проблемной кросс-компиляции.Исполняемый файл как-то поврежден при копировании

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

./re8k_interface-tgt: line 1: syntax error: unexpected word (expecting ")")

Теперь я знаю, что исходный файл в порядке, скопировав его на устройство и запустить его, так что я знаю, что что-то делать с процессом копирования файла, либо при загрузке, либо при записи в объект QFile. Вот как я это делаю сейчас:

//Call to download 
QUrl ulrTemp("//" + downloadUrls[downloadStep].arg(ui->sbID->text())); 
ulrTemp.setScheme("file"); 

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

poReply = downloadNetworkManager->get(QNetworkRequest(ulrTemp)); 

connect(poReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(slotTransferProgress(qint64,qint64))); 
connect(poReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(slotTransferError(QNetworkReply::NetworkError))); 


//When finished 
QByteArray downloadedData; 
downloadedData = reply->readAll(); 

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

static const QString tempFilePath = QDir::tempPath(); 

QFile file(tempFilePath + "/" + downloadNames[downloadStep]); 

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

    return; 
} 

QDataStream stream(&file); 

stream << downloadedData; 

file.close(); 

P.s .: Я понимаю, о необходимости установки разрешений,

Скопированная размер файла точно совпадает с оригиналом. Итак, где проблема, которую я не вижу?

+0

Вы также убедитесь, что содержимое соответствует, а не только размер? Действительно ли они разные? 'md5' или что-то в этом роде расскажет вам легко. – Steve

ответ

2

При записи массива байтов в QDataStream длина массива также записывается.

Просто не используйте поток данных, используйте QFile, или, лучше QTemporaryFile напрямую.

В приведенном ниже примере показано, как использовать C++ 11 и Qt 5, чтобы сделать это очень просто:

Writing to: /var/folders/yy/2tl/T/download-29543601.L91178 
Wrote 55015 bytes. 
Downloaded 55015 of -1 bytes 
Wrote 7572 bytes. 
Wrote 6686 bytes. 
Wrote 5104 bytes. 
Downloaded 74377 of 74377 bytes 
Successfully wrote /var/folders/yy/2tl/T/download-29543601.L91178 
#include <QCoreApplication> 
#include <QNetworkAccessManager> 
#include <QNetworkReply> 
#include <QTemporaryFile> 
#include <QUrl> 
#include <QByteArray> 
#include <QTextStream> 
#include <QDebug> 
#include <cstdio> 

QTextStream out(stdout); 
QTextStream in(stdin); 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    QNetworkAccessManager mgr; 

    auto url = QUrl("http://stackoverflow.com/questions/29543601/" 
        "executable-getting-somehow-corrupted-when-being-copied"); 
    auto reply = mgr.get(QNetworkRequest(url)); 

    QTemporaryFile file; 
    if (!file.open()) { 
     qDebug() << "Can't open file for writing."; 
     return -1; 
    } 
    out << "Writing to: " << file.fileName() << endl; 

    QObject::connect(reply, &QNetworkReply::downloadProgress, [](qint64 rx, qint64 total) { 
     qDebug() << "Downloaded" << rx << "of" << total << "bytes"; 
    }); 

    QObject::connect(reply, &QIODevice::readyRead, [reply, &file]{ 
     auto data = reply->readAll(); 
     auto written = file.write(data); 
     if (data.size() != written) { 
     qDebug() << "Write failed, wrote" << written << "out of" << data.size() << "bytes."; 
     } else { 
     qDebug() << "Wrote " << written << "bytes."; 
     } 
    }); 

    QObject::connect(reply, &QNetworkReply::finished, [reply, &file]{ 
     if (reply->error() != QNetworkReply::NoError) { 
     qDebug() << "The request was unsuccessful. Error:" << reply->error(); 
     qApp->quit(); 
     return; 
     } 
     if (file.flush()) { 
     out << "Successfully wrote " << file.fileName(); 
     out << "\nPress Enter to remove the file and exit." << flush; 
     in.readLine(); 
     } else { 
     qDebug() << "The file flush has failed"; 
     } 
     qApp->quit(); 
    }); 

    return a.exec(); 
} 
+0

Спасибо за ответ, это сработало! Странно, что я не рассматривал использование QFile напрямую, переходя прямо к QDataStream после ошибочного использования QTextStream. О QTemporaryFile, я не думаю, что это будет полезно для меня, так как я фактически загружаю много файлов в temp, а затем загружаю их на FTP-сервер (читая руководство, мне казалось, что QTemporaryFile предназначен для операций с одним временным файлом). – Momergil

+1

@Momergil. Вам вообще не нужен «QTemporaryFile». Просто сохраняйте данные в памяти до завершения загрузки. При необходимости механизм подкачки будет выгружать вещи на диск. Если вы настаиваете на использовании файлов, то это должно быть сделано несколько иначе, поскольку 'readAll', когда он используется только один раз, когда запрос завершен, заполняет все содержимое файла в памяти, поэтому он на самом деле контрпродуктивен (удваивает использование ОЗУ) чтобы явно записать его в файл. См. Обновленный код. –

Смежные вопросы