Executable getting somehow corrupted when being co

2020-04-17 03:09发布

I'm using Qt's QNetworkAccessManager to download a file from a place (currently the local machine, but in the future it will be an HTTP server) and temporarily store it in the TEMP file (linux ubuntu). The problem I've found is that the file (which is an executable) gets corrupted in the process: when I try to run the file as executable, it returns a classical error of problematic cross-compilation.

Now that's interesting because the file is a executable for a Embedded Linux Device - I'm downloading the executable to my TEMP so I may send it later to the device. When that happens (using FileZilla), though, this error message appears:

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

Now I know the original file is fine by copying it to the device and running it, so I'm aware it has something to do with the process of copying the file, either when downloading or when writing to a QFile object. Here is how I'm doing it for 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();

P.s.: I'm aware of the necessity of setting permissions

The copied file size matches exactly the original. So, where is the problem I can't see?

1条回答
聊天终结者
2楼-- · 2020-04-17 04:03

When writing a byte array to a QDataStream, the array's length is written as well.

Simply don't use the data stream, use QFile, or, better QTemporaryFile directly.

The example below demonstrates how to leverage C++11 and Qt 5 to make it really 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();
}
查看更多
登录 后发表回答