In my project, I am attempting to download a YouTube profile picture. The YouTube API returns this link https://yt3.ggpht.com/-7ipuUvDjVT8/AAAAAAAAAAI/AAAAAAAAAAA/hSPOcUsb1nw/s240-c-k-no-mo-rj-c0xffffff/photo.jpg
However, using the same function for downloading files from my own website doesn't work with this URL. I get QNetworkReply::NetworkError(ProtocolUnknownError) in the application output.
Here is my code:
QByteArray downloadFileData(QString url)
{
QNetworkRequest request;
request.setUrl(QUrl(url));
QNetworkReply *reply = manager->get(request);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
if(reply->error() == QNetworkReply::NoError)
{
return reply->readAll();
}
else
{
qDebug() << reply->error();
}
reply->deleteLater();
return "";
}
When I pass that url to this function, I get that error. What is going on?
Thanks for your time
Related
My API server is turned off and i run following code.
I dont understand why QNetworkReply::OperationCanceledError error enum is returned instead of QNetworkReply::TimeoutError. What is wrong? Am i doing something wrong or is it Qt bug?
From documentation that error should be if "the operation was canceled via calls to abort() or close() before it was finished."
I see no reason for that.
QByteArray encodedData = data.toUtf8();
QUrl url("http://myapi/jsonrpc");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkAccessManager manager;
manager.setTransferTimeout(500);
QNetworkReply* reply = manager.post(request, encodedData);
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() != QNetworkReply::NoError) {
QString errorMsg = QString("HTTP Network request has failed. Code: ") + QVariant::fromValue(reply->error()).toString();
delete reply;
// error
// here i got QNetworkReply::OperationCanceledError
}
QByteArray response = reply->readAll();
//ok
So I have this code:
QUrl url("http://...");
QNetworkRequest request(url);
QNetworkReply *reply = m_networkManager->get(request);
connect(reply, SIGNAL(finished()), SLOT(onRequestCompleted()));
connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),SLOT(onError(QNetworkReply::NetworkError)));
and I cant get signal to the other fuction
void IpResolver::onRequestCompleted()
{
QString webContent;
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if (reply)
{
if (reply->error() == QNetworkReply::NoError)
{
QString webContent = reply->readAll();
}
}
}
I cant figure out the solution, help please.
I don't know what exactly you want, but:
Why do you use reply pointer instead of some kind onRequestCompleted(QNetworkReply *reply)?
If you do so:
QUrl url("http://...");
QNetworkRequest request(url);
connect(m_networkManager, &QNetworkAccessManager::finished, this, &IpResolver::onRequestCompleted);
m_networkManager->get(request);
And your slot will be, for example:
void IpResolver::onRequestCompleted(QNetworkReply *reply)
{
QString webContent;
if (reply->error() == QNetworkReply::NoError)
webContent = reply->readAll();
}
I am trying to get the content of a HTTP request into a QString variable with Qt and C++
QNetworkAccessManager networkManager;
QUrl url("https://someurl.test.com/this-actually-exists");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply* currentReply = networkManager.get(request); // GET
QString reply = QTextCodec::codecForMib(1015)->toUnicode(currentReply->readAll());
Still, the variable reply seems to stay empty. Obviously, I misunderstand the documentation. How do I get this to perform?
You can use two different ways even the synchronous or asynchronous ways to do this. The asynchronous way is :
connect (&networkManager , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(done(QNetworkReply*)));
networkManager.get(request);
And you should read the contents from the returned reply in the slot connected to finished signal in the following way :
void net::done(QNetworkReply * reply)
{
if (reply->error() == QNetworkReply::NoError)
{
data = QString(reply->readAll ());
}
else
{
data = QString(reply->errorString ());
}
}
The synchronous way is like :
QNetworkReply *reply = networkManager.get(request);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
loop.exec();
QByteArray bts = reply->readAll();
QString str(bts);
Here you use an event loop to wait until the reply is finished and then read the available bytes and get the string.
I need to assume you're running an application with an event-loop in place? If not, then it's a bit harder...
If so, replace your last line that builds the reply QString:
connect(currentReply, SIGNAL(finished()), this, SLOT(gotAReply()));
Then you'll have to define another method in your class as a slot that gets triggered as soon as that reply got filled:
void gotAReply()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(QObject::sender());
if (reply)
{
if (reply->error() == QNetworkReply::NoError)
{
QString replyText( reply->readAll() );
}
reply->deleteLater();
}
}
Don't forget: for Signals and Slot to work your class declaration must contain the Q_OBJECT macro.
QString My_class::My_Method()
{
QNetworkAccessManager *manager= new QNetworkAccessManager(this);
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(ReplayFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl(My_URL)));
return str;
}
void My_class::ReplayFinished(QNetworkReply *replay)
{
QString buffer;
if(replay->isOpen())
{
buffer=replay->readAll();
//treatment on the buffer and the public Qstring 'str'(declared in My_class.h) is updated
}
}
Hi,
the problem is that when calling the My_method() in the main, the QString str is empty because it was returned that way without waiting for the ReplayFinished to update it.
What could be the solution to wait until the job is complete so I can get the proper information, not skipping it and returning something else.
Thank you.
You can use an event loop to wait until the reply is finished and then read the available bytes and return the string :
QString My_class::My_Method()
{
QNetworkAccessManager manager;
QNetworkReply *reply = manager.get(QNetworkRequest(QUrl(My_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();
QString str(bts);
delete reply;
return str;
}
I'm trying to use Qt to download the html code from the following url:
http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=nucleotide&cmd=search&term=AB100362
this url will re-direct to
www.ncbi.nlm.nih.gov/nuccore/27884304
I try to do it by following way, but I cannot get anything.
it works for some webpage such as www.google.com, but not for this NCBI page. is there any way to get this page??
QNetworkReply::NetworkError downloadURL(const QUrl &url, QByteArray &data)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
if (reply->error() != QNetworkReply::NoError)
{
return reply->error();
}
data = reply->readAll();
delete reply;
return QNetworkReply::NoError;
}
void GetGi()
{
int pos;
QString sGetFromURL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi";
QUrl url(sGetFromURL);
url.addQueryItem("db", "nucleotide");
url.addQueryItem("cmd", "search");
url.addQueryItem("term", "AB100362");
QByteArray InfoNCBI;
int errorCode = downloadURL(url, InfoNCBI);
if (errorCode != 0 )
{
QMessageBox::about(0,tr("Internet Error "), tr("Internet Error %1: Failed to connect to NCBI.\t\nPlease check your internect connection.").arg(errorCode));
return "ERROR";
}
}
That page appears to have a redirect.
From the Qt docs for 4.6:
Note: When the HTTP protocol returns a
redirect no error will be reported.
You can check if there is a redirect
with the
QNetworkRequest::RedirectionTargetAttribute
attribute.