Qt 5 C++ HTTP POST issues - c++

I have been trying to use C++ and Qt for a HTTP POST request and after very much research this is the only way I could get the program to even compile. 95% of the examples had plenty of errors and wanted libraries that no longer exist. The issue is that when I do use this code its "reply" equals null... Is there any better way to do a HTTP POST request, and what am I doing wrong?
QEventLoop eventLoop;
QUrl myURL(QString("http://example.com/"));
QNetworkRequest request(myURL);
QNetworkAccessManager mgr;
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
QUrlQuery qu;
qu.addQueryItem("unm", aUser);
qu.addQueryItem("pwd", aPass);
QUrl params;
params.setQuery(qu);
QNetworkReply *reply = mgr.post(request, params.toEncoded());
qDebug() << "Success" <<reply->readAll();

You have to execute the event loop before reading the reply. Qt documentation says
QNetworkAccessManager has an asynchronous API.
So you have to wait till the reply is finished. That is the purpose of using an QEventLoop. you need to block the calling thread until QNetworkAccessManager emits finished(QNetworkReply*).
Everything is fine in your code, except you do not execute the QEventLoop.
Put eventLoop.exec() after sending the request.
QUrl myURL(QString("http://example.com"));
QNetworkRequest request(myURL);
QNetworkAccessManager mgr;
QUrlQuery qu;
qu.addQueryItem("unm", aUser);
qu.addQueryItem("pwd", aPass);
QUrl params;
params.setQuery(qu);
QNetworkReply *reply = mgr.post(request, params.toEncoded());
QEventLoop eventLoop;
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
eventLoop.exec();
qDebug() << "Success" <<reply->readAll();

Related

Web service in blackberry 10

I am developing a BlackBerry 10 apps with Cascades (C++ programming language) right now. Can anyone tell me how do i make a call to web service in BlackBerry 10: Cascades? I'm just a beginner, so i don't really know anything. Thanks for your answer
void GetWeb::start(const QString &str)
{
QNetworkRequest request = QNetworkRequest();
request.setUrl(QUrl(str));
QNetworkAccessManager *networkAccessManager = new QNetworkAccessManager(this);
connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(requestFinished(QNetworkReply*)));
networkAccessManager->get(request);
}
void GetWeb::requestFinished(QNetworkReply* reply)
{
if (reply->error() == QNetworkReply::NoError)
{
emit complete(reply->readAll());
}
reply->deleteLater();
}
In this case I am emiting the resulting string as a signal, but you could also just use the reply->readAll() string directly if you wished...
There's a few moving parts to sending a network request using Qt. Here's the example Qt uses:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
So what you do is create a QNetworkAccessManager object, which handles the actual process of sending the request and processing the response. You then connect the signal that the manager emits when the QNetworkRequest has finished to a slot you've created called replyFinished which takes QNetworkReply * as a parameter, that might look like this:
void MyClass::replyFinished(QNetworkReply *serverResponse)
{
//do something with the response
}
You then use the managers get method to pass your QNetworkRequest, which you can create like it has been there, or separately. And that's about it, that's a minimal example that'll send a HTTP request to http://qt-project.org and return a response containing the data from the page, you can extend out from there to do things like get JSON or XML.
Example from: QtNetwork documentation

Qt Can't download file using QNetworkAccessManager

In my project, I need to download a simple .txt file. I created a function to download the file based on the url:
void MainWindow::downloadFile(const QString &url, const QString &aPathInClient)
{
QNetworkAccessManager* m_NetworkMngr = new QNetworkAccessManager(this);
QNetworkReply *reply = m_NetworkMngr->get(QNetworkRequest(QUrl(url)));
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QUrl aUrl(url);
QFileInfo fileInfo=aUrl.path();
QFile file(aPathInClient+"\\"+fileInfo.fileName());
file.open(QIODevice::WriteOnly);
file.write(reply->readAll());
delete reply;
}
When my program is ran, the file is created with the correct file name, but the file is empty. The file name can only be obtained by my program if is connect to the webpage. What am I forgetting? I get no errors on build and have included all the necessary libraries.
Thanks :)
EDIT:
All is well, my problem was my link used https instead of http.
I haven't ever used the 'write' function for writing to a QFile. Try the following approach:
QFile file(aPathInClient+"\\"+fileInfo.fileName());
file.open(QIODevice::WriteOnly);
QTextStream out(&file);
out << "This file is generated by Qt\n";
EDIT: The above was just to check whether the file is being written to correctly or not. Now since it has been verified, you can try:
out << reply->readAll();

How to connect QNetworkReply signal to progress bar in qt

In the code below:
connect(network_access_manager_, SIGNAL(finished(QNetworkReply*)),
this, SLOT(onRequestCompleted_progress(QNetworkReply *)));
network_access_manager_->get(request);
The point is that while the downloading the file via get(request) is in progress I'd like to connect the signal from QNetworkReply to progressBar but I simply don't see how am I suppose to do it? The QNetworkReply is unnamed.
Any ideas?
network_access_manager_->get(request); returns QNetworkReply*, so
QNetworkReply *reply = network_access_manager_->get(request);
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(......))
will serve.

Qtimer fires before QNetworkAccessManager finished

Im making a connection every X sec. but in case net bandwidth is overloaded timer fires before QNetworkAccessManager sends finished signal and app crashes.
MainWindow::construct:
pTimer = new QTimer(this);
connect(pTimer, SIGNAL(timeout()), this, SLOT(connect()));
pTimer->start(5000);
MainWindow::connect()
pNetworkManager = new QNetworkAccessManager(this);
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(result(QNetworkReply*)));
pNetworkManager->get(QNetworkRequest(url));
MainWindow::result(QNetworkReply *reply) processes the response
how to check if QNetworkAccessManager isFinished before timer fires again?
Don't create a network manager per request, but only one network manager for your class. Otherwise you leak managers with each request until the mainwindow is destroyed.
QNetworkManager::get returns the pointer to the QNetworkReply representing the request. You can store that reply in a QPointer, connect to its signals, check QNetworkReply::isFinished() etc. to track whether the request is still running or not.
Why not simply launch timer after request finished?
pTimer = new QTimer(this);
pTimer->setSingleshot(true);
connect(pTimer, SIGNAL(timeout()), this, SLOT(connect()));
pTimer->start(5000);
pNetworkManager = new QNetworkAccessManager(this);
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(result(QNetworkReply*)));
connect(pNetworkManager, SIGNAL(finished(QNetworkReply*)), pTimer, SLOT(start()));

Writing a QNetworkReply to a file

I'm downloading a file using QNetworkAccessManager::get but unlike QHttp::get there's no built-in way to directly write the response to a different QIODevice.
The easiest way would be to do something like this:
QIODevice* device;
QNetworkReply* reply = manager.get(url);
connect(reply, SIGNAL(readyRead()), this, SLOT(newData()));
and then in newData slot:
device->write(reply->readAll());
But I'm not sure if this is the right way, maybe I missed something.
That looks correct. I would use the lower-level forms of read() and write(), not the QByteArray ones, which do not properly support error handling, but other than that, it looks fine.
Are you having problems with it?
Better use the finished signal to read all the contents at the end of the download process. An example (remove the event loop and use a new slot to make it asynchronous):
QNetworkAccessManager manager;
QEventLoop loop;
QNetworkReply *reply = manager.get( request );
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
QFile file( "YOUR FILE" );
file.open(QIODevice::WriteOnly);
file.write(reply->readAll());
delete reply;