Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] Cannot download using QNetworkAccessManager
Forum Updated to NodeBB v4.3 + New Features

[Solved] Cannot download using QNetworkAccessManager

Scheduled Pinned Locked Moved General and Desktop
14 Posts 2 Posters 3.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • sierdzioS Offline
    sierdzioS Offline
    sierdzio
    Moderators
    wrote on last edited by
    #4

    They don't. You are simply doing it wrong in your MainWindow. Downloader class is done correctly.

    (Z(:^

    1 Reply Last reply
    0
    • I Offline
      I Offline
      igorland
      wrote on last edited by
      #5

      sierdzio. Thank you again. Can you please elaborate what exactly I am doing wrong? Cheers!

      1 Reply Last reply
      0
      • sierdzioS Offline
        sierdzioS Offline
        sierdzio
        Moderators
        wrote on last edited by
        #6

        @
        Downloader d;
        d.doDownload();

        QString metarData;
        // This is WAY too soon!
        metarData = d.getData();
        @

        instead of getting the data in the very same method, you need to wait until the reply comes. Either use a forever loop (ugly solution!), or, just like you are doing in Downloader: respond to replyFinished().

        (Z(:^

        1 Reply Last reply
        0
        • I Offline
          I Offline
          igorland
          wrote on last edited by
          #7

          sierdzio,

          Sorry, I am trying to understand what you mean by "like you are doing in Downloader: respond to replyFinished()."

          I have been searching more on this and another suggestion that I have come across with was to put the d object on the heap. I changed it to:

          [code]
          Downloader* d = new Downloader;
          d->doDownload();

          QString metarData;
          metarData = d->getData();
          ui->plainTextEdit->setPlainText(metarData);
          

          [/code]

          Still no luck... Sorry for being so n00b.. ))

          1 Reply Last reply
          0
          • sierdzioS Offline
            sierdzioS Offline
            sierdzio
            Moderators
            wrote on last edited by
            #8

            When the button is clicked, only send the request (doDownload). Then getData in a slot connected to finished(). You need to refactor the code bit. Here is a small helper:
            @
            // Downloader
            signals:
            void downloadFinished(Downloader *d);
            ...
            void Downloader::replyFinished (QNetworkReply *reply) {
            ...
            emit downloadFinished(this);
            }

            // MainWindow
            void MainWindow::on_pushButton_clicked()
            {
            Downloader *d = new Downloader(this);
            connect (d, SIGNAL(downloadFinished(Downloader *)), this, SLOT(someSlot(Downloader *)));
            d->doDownload();
            ...
            }
            ...
            void MainWindow::someSlot(Downloader *down)
            {
            QString metarData;
            metarData = down->getData();
            // Optional:
            down->deleteLater();
            }
            @

            (Z(:^

            1 Reply Last reply
            0
            • I Offline
              I Offline
              igorland
              wrote on last edited by
              #9

              sierdzio. You do belong to the Hall of Fame for your support and knowledge. I am still trying to nail it down. This is what I have now:

              [code]
              #include "Downloader.h"

              Downloader::Downloader(QObject *parent) :
              QObject(parent)
              {
              }

              void Downloader::doDownload()
              {
              manager = new QNetworkAccessManager(this);
              connect(manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)));
              manager->get(QNetworkRequest(QUrl("ftp://ftp.com/ftp.TXT")));

              }

              void Downloader::replyFinished (QNetworkReply *reply)
              {
              if(reply->error())
              {
              qDebug() << "ERROR!";
              qDebug() << reply->errorString();
              }
              else
              {
              dataByte = reply->readAll();
              emit downloadFinished(this);
              reply->deleteLater();
              }
              }

              void Downloader::downloadFinished(Downloader *dfinished)
              {
              QString dataStr(dataByte);
              dataFinal = dataStr;
              dfinished->deleteLater();
              }

              QString Downloader::getData()
              {
              return dataFinal;
              }

              [/code]

              MainWindow.cpp
              [code]
              #include "mainwindow.h"
              #include "ui_mainwindow.h"
              #include "Downloader.h"

              MainWindow::MainWindow(QWidget *parent) :
              QMainWindow(parent),
              ui(new Ui::MainWindow)
              {
              ui->setupUi(this);
              }

              MainWindow::~MainWindow()
              {
              delete ui;
              }

              void MainWindow::on_pushButton_clicked()
              {
              d = new Downloader(this); // declared in header
              connect(d, SIGNAL(downloadFinished(Downloader *)), this, SLOT(someSlot(Downloader *)));
              d->doDownload();

              ui->plainTextEdit->setPlainText(metarData);
              

              }

              void MainWindow::someSlot(Downloader* down)
              {
              metarData = d->getData();
              down->deleteLater();
              }
              [/code]

              Now, I get a weird error saying that
              [code]
              multiple definition of Downloader::downloadFInished(Downloader*)
              first define here
              [/code]

              Weird, because I only have it defined in Downloader.h
              [code]
              #ifndef DOWNLOADER_H
              #define DOWNLOADER_H

              #include <QObject>
              #include <QNetworkAccessManager>
              #include <QNetworkRequest>
              #include <QNetworkReply>
              #include <QUrl>
              #include <QDateTime>
              #include <QFile>
              #include <QDebug>
              #include <QEventLoop>

              class Downloader : public QObject
              {
              Q_OBJECT
              public:
              explicit Downloader(QObject *parent = 0);
              void doDownload();
              QString getData();

              signals:
              void downloadFinished(Downloader *dfinished);

              public slots:
              void replyFinished (QNetworkReply *reply);

              private:
              QNetworkAccessManager *manager;
              QByteArray dataByte;
              QString dataFinal;
              };

              #endif // DOWNLOADER_H
              [/code]

              I love Qt, but it is so discouraging to spend many days on something that took me a day to figure out how to do it in libcurl and Java.

              sierdzio. Thank you again!

              1 Reply Last reply
              0
              • sierdzioS Offline
                sierdzioS Offline
                sierdzio
                Moderators
                wrote on last edited by
                #10

                If you want easy, go with QHttp or QFtp ;) QNAM is powerful, but also more complicated. The asynchronous paradigm is much better, but also more complicated and harder to get.

                In your case, you've hit a small detail that some people new to Qt do stumble upon: a signal is not a method, only the slots need implementation. So, you should delete all this:
                @
                // Delete!
                void Downloader::downloadFinished(Downloader *dfinished)
                {
                QString dataStr(dataByte);
                dataFinal = dataStr;
                dfinished->deleteLater();
                }
                @

                And only leave this line in the header file:
                @
                signals:
                void downloadFinished(Downloader *dfinished);
                @

                (Z(:^

                1 Reply Last reply
                0
                • I Offline
                  I Offline
                  igorland
                  wrote on last edited by
                  #11

                  sierdzio. You are the MAN! Thank you. Now the file is getting downloaded. I see it in qDebug. One problem still remains though due the asynchronous process, I believe. The thing is that when in the following code:

                  [code]
                  void MainWindow::on_pushButton_clicked()
                  {
                  d = new Downloader(this);
                  d->doDownload();
                  connect(d, SIGNAL(downloadFinished(Downloader *)), this, SLOT(someSlot(Downloader *)));

                  qDebug() << "MetarData: " <&lt; metarData;
                  ui-&gt;plainTextEdit->setPlainText(metarData);
                  

                  }

                  void MainWindow::someSlot(Downloader* down)
                  {
                  metarData = d->getData();
                  down->deleteLater();
                  }
                  [/code]

                  when I do this:
                  [code]
                  ui->plainTextEdit->setPlainText(metarData);
                  [/code]

                  it does not do anything. Apparently, it does not wait for the file to be first downloaded and goes straight to setPlainText because

                  [code]
                  qDebug() << "MetarData: " << metarData
                  [/code]

                  returns an empty string. In my main application, where metarData is further passed to other functions, I even get a CTD.
                  I thought that connect should take care of this and the code would wait for the full data to be downloaded first.

                  Thanks!

                  1 Reply Last reply
                  0
                  • I Offline
                    I Offline
                    igorland
                    wrote on last edited by
                    #12

                    On the other hand, I can move it to the someSlot function and let it be there. Anyways, thanks a lot for your great help!

                    1 Reply Last reply
                    0
                    • sierdzioS Offline
                      sierdzioS Offline
                      sierdzio
                      Moderators
                      wrote on last edited by
                      #13

                      You assign the variable at the wrong time. Do this instead:
                      @
                      void MainWindow::someSlot(Downloader* down)
                      {
                      metarData = d->getData();
                      ui->plainTextEdit->setPlainText(metarData);
                      down->deleteLater();
                      }
                      @

                      (Z(:^

                      1 Reply Last reply
                      0
                      • I Offline
                        I Offline
                        igorland
                        wrote on last edited by
                        #14

                        Yes. Thanks a lot. Very much appreciated.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved