StEvUgnIn
StEvUgnIn

Reputation: 163

Why am I unable to download a file using this code

I'm working on a school project and since many weeks I try to adapt this code, but it returns me an empty QByteArray. I really need this code, cause my whole project is based on this code.

Here is my code :

namespace Pixmap {
static QByteArray *bitmap;

QPixmap downloadPixmap(const QUrl &url);
QPixmap downloadPixmap(const QString &url);
}

QPixmap Pixmap::downloadPixmap(QUrl const& url)
{
QNetworkAccessManager access_manager;
QNetworkReply *reply = access_manager.get(
            QNetworkRequest(url)
            );
QPixmap pix;
bitmap = &reply->readAll();
reply->close();
if (/*!bitmap->isNull() && */ !reply->readAll().isNull()) {
    pix.loadFromData(*bitmap);
    return pix;
} else {
    // Apparemment aux tests 1 et 2 pas d'erreurs.
    qDebug("Damned");
    return QPixmap();
}
}

QPixmap Pixmap::downloadPixmap(QString const& url)
{
    return downloadPixmap(QUrl(url));
}

I thought the solution was to use a static variable to receive data's reply, but it wasn't.

Could you give some advice, please.

I'm developping on Windows currently with Qt 5.3.

Thank you all.

Edit 1: So I merged Nejat's second solution with this.

The result is not concluding. The debugger advices me HTTP protocol is not supported.

Can't download "http://127.0.0.1/Acompte/MCD_Ordi.jpg" : "Protocol type not supported"

if (reply->waitForReadyRead(-1)) //! @bug this does not work as supposed, waitForRead returns false and returns INSTANTLY!!
    qDebug() << "ReadyRead yeha!!!";
if (reply->error()) {
    qDebug() << "Can't download" << reply->url().toString()
            << ":" << reply->errorString();
} else {
    bitmap = reply->readAll();
    qDebug() << "Saving IMG";
}

What does the problem come from according to you ? I'm still new to Qt Widgets and I don't master QObject::connect.

Edit 2: The URL is local, there it is : 127.0.0.1/Acompte/MCD_Ordi.jpg I am able to view it with my web browser, but not within my application. So I don't see what's the problem.

Now I try, it returns the message that HTTP protocol is not supported.

Upvotes: 1

Views: 161

Answers (3)

StEvUgnIn
StEvUgnIn

Reputation: 163

So I merged Nejat's second solution with this.

The result is not concluding. The debugger advices me HTTP protocol is not supported.

Can't download "http://127.0.0.1/Acompte/MCD_Ordi.jpg" : "Protocol type not supported"

if (reply->waitForReadyRead(-1)) //! @bug this does not work as supposed, waitForRead returns false and returns INSTANTLY!!
    qDebug() << "ReadyRead yeha!!!";
if (reply->error()) {
    qDebug() << "Can't download" << reply->url().toString()
            << ":" << reply->errorString();
} else {
    bitmap = reply->readAll();
    qDebug() << "Saving IMG";
}

What does the problem come from according to you ? I'm still new to Qt Widgets and I don't master QObject::connect.

Edit : This request is blocked by a hidden proxy at work.

Plus be aware, this code will not create a memory leak :

QEventLoop *loop = new QEventLoop;
QObject::connect(reply, SIGNAL(finished()), loop, SLOT(quit()));
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), loop, SLOT(quit()));
loop->exec();

You don't need to delete QObject derived objects.

Upvotes: 0

Nejat
Nejat

Reputation: 32645

You can also do it in an asynchronous way by connecting the finished signal of the QNetworkAccessManager to a slot :

connect(&access_manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onFinished(QNetworkReply*)));

And read data there :

void onFinished(QNetworkReply* reply)
{

   if (reply->error() == QNetworkReply::NoError)
   {
       QByteArray bts = reply->readAll();

       ...
   }
}

You can also use an event loop to wait until the reply is finished and then read the available bytes :

QNetworkAccessManager access_manager;

QNetworkReply *reply = access_manager.get(QNetworkRequest(url));

QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
loop.exec();

QByteArray bts = reply->readAll();
...

Upvotes: 1

dfranca
dfranca

Reputation: 5322

You must set the finished signal of your access_manager

connect(access_manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(myFunctionToHandleReply(QNetworkReply *)));

And your myFunctionToHandleReply must handle the reply:

void MyApp::myFunctionToHandleReply(QNetworkReply *reply) {
    QByteArray data = reply->readAll();
}

The documentation with the signals of QNetworkAccessManager: http://doc.qt.io/qt-5/qnetworkaccessmanager.html

Upvotes: 1

Related Questions