Executable file becomes invalid when copied
I am using Qt QNetworkAccessManager to download a file from a location (it is currently a local machine, but in the future it will be an HTTP server) and temporarily stores it in a TEMP file (linux ubuntu). The problem I have found is that the file (executable) is corrupted in the process: when I try to run the file as an executable, it returns the classic problematic cross-compilation error.
Now this is interesting because the file is an executable for an embedded Linux device - I load the executable in my TEMP so I can send it later to the device. However, when this happens (using FileZilla) the following error message appears:
./re8k_interface-tgt: line 1: syntax error: unexpected word (pending ")")
Now I know the original file is good by copying it to the device and running it, so I know it has something to do with the process of copying the file on upload or when writing to the QFile object. This is how I do it now:
//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();
Ps: I know about the need to set permissions
The copied file size is the same as the original. So where is the problem that I am not seeing?
source to share
When writing an array of bytes, the QDataStream
length of the array is also recorded.
Just don't use data flow, use QFile
or better QTemporaryFile
.
The example below shows how to use C ++ 11 and Qt 5 to make it very simple:
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();
}
source to share