Solved QNetworkAccessManager reply is always empty
-
@Bonnie sweet, not its realy ok :)
One very last thing, I have noticed that the read content contains new rows as "\r\n" which after write() makes double empty rows instead of single ones.Im ok to fix it by:
int start_pos = 0; QByteArray from("\r\n"); QByteArray to("\n"); while((start_pos = read.indexOf(from, start_pos)) != -1) { read.replace(start_pos, from.length(), to); start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' }
but im wondering if this can be prevented by setting header maybe?
-
Are you running the code in Windows?
And the original text from the ini on the network should be "\n"?
This is whatQIODevice::Text
supposed to do in Windows: replace "\n" to "\r\n" when writing. -
Yes on Windows,
however file is stored on linux network and i odnt know if there are \n or \r\n
but when i qDebug() << read; even before QIODevice::Text i can see there are \r\n, therefore.
Then i replace it with just \n and then qhen opening file via QIODevice::Text it writes just fine... therefore QIODevice::Text has no impact... -
@shokarta
I've tested on my Windows,QIODevice::Text
does do what it is supposed to do.
The thing is, "\r\n" is the right line terminator in Windows, so you will see a normal line break with a "\r\n".
But if your original text is "\r\n", then it will be translated to "\r\r\n", that's not right.
So I think you can just delete thatQIODevice::Text
flag. -
@Bonnie said in QNetworkAccessManager reply is always empty:
Yes, I know sometimes we need to wait for the reply to be finished.
So connect the QNetworkReply::finished() signal then...
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
It doesn't look a pretty good idea to mess with the event loop. And not needed either
-
@Pablo-J-Rogina said in QNetworkAccessManager reply is always empty:
It doesn't look a pretty good idea to mess with the event loop. And not needed either
There are cases that we need to get response synchronously.
In the OP's case for example, the function need to return a result of true / false.
And this is a typical usage of QEventLoop: to wait until a signal.
I've already said it is not recommended.
But anyone should be free to use it if he insists a synchronous request. -
@Bonnie so far im using your option, however in dev version of the application i will try the lamba solution
@J-Hilk so far I have this:in .h file:
public: explicit MSSQL(QObject *parent = nullptr); Q_INVOKABLE void checkSettings(); private: QString settingsFile = "settings.ini"; void onNetworkReplyFinished(QNetworkReply *reply);
and in cpp file:
MSSQL::MSSQL(QObject *parent) : QObject(parent) { } void MSSQL::checkSettings() { qDebug() << "test1"; QNetworkAccessManager nam; connect(nam, &QNetworkAccessManager::finished, this, &MSSQL::onNetworkReplyFinished); QNetworkRequest request(QUrl("http://someinifilelocation.ini")); // PROD nam.get(request); return; } void MSSQL::onNetworkReplyFinished(QNetworkReply *reply) { qDebug() << "test2"; qDebug() <<Q_FUNC_INFO << "QNetworkAccessManager::finished"; QByteArray read = reply->readAll(); QNetworkReply::NetworkError error = reply->error(); reply->deleteLater(); if(error) { qDebug() << "Terminal DB Error: Remote INI file not reachable: " << error; return; } else { if(read.isEmpty()) { qDebug() << "Terminal DB Error: Remote INI file response is empty"; return; } QByteArray newFile = QCryptographicHash::hash(read, QCryptographicHash::Md5); QString fileName(QDir::currentPath() + "/" + settingsFile); QFile file(fileName); if(!file.open(QIODevice::ReadWrite)) { qDebug() << "Terminal DB Error: Creating local INI:" << file.error() << file.errorString(); return; } QByteArray oldFile = QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5); if (oldFile != newFile) { qDebug() << "Terminal DB: Downloading new INI file from remote source"; file.resize(0); file.write(read); } file.close(); refreshParameters(); } }
but im having debug only on "test1"... test2 never happens :(
what do I do wrong? -
Hi,
Because "nam" is a function local variable that will be destroyed as soon as your function ends and thus everything connect to it will be disconnected.
-
@SGaist said in QNetworkAccessManager reply is always empty:
Because "nam" is a function local variable that will be destroyed as soon as your function ends and thus everything connect to it will be disconnected.
so &nam would be the solution? or sendig it with?
any suggestion how to handle this? -
@shokarta
You could move
QNetworkAccessManager nam;
to the .h inside class so its a class member.
Then it will live as long as the class and you will no such issues. -
@mrjj said in QNetworkAccessManager reply is always empty:
You could move
QNetworkAccessManager nam;So i did this, however it works very fine only the first time function checkSettings() is called, but second and all other times it always fails on:
if(read.isEmpty())
so how come its always empty since then?
do I need to clear the buffer after each slot is set? -
@shokarta Did you move
connect(nam, &QNetworkAccessManager::finished, this, &MSSQL::onNetworkReplyFinished);
to the constructor of your class? As now you connect it each time checkSettings() is called.
-
@shokarta
here, have a working class to use -
well, yes, i did all those, now it works, however still all app is freezed between i ask for reply and i receive it...
so i have this:
.h file:
public: explicit MSSQL(QObject *parent = nullptr); Q_INVOKABLE void checkSettings(); Q_INVOKABLE bool checkConnection(); private: QString settingsFile = "settings.ini"; QNetworkAccessManager nam; void onNetworkReplyFinished(QNetworkReply *reply);
and in cpp file:
MSSQL::MSSQL(QObject *parent) : QObject(parent) { connect(&nam, &QNetworkAccessManager::finished, this, &MSSQL::onNetworkReplyFinished); } void MSSQL::checkSettings() { QNetworkRequest request(QUrl("http://some/settings.ini")); // PROD nam.get(request); qDebug() << "test1"; return; } void MSSQL::onNetworkReplyFinished(QNetworkReply *reply) { QByteArray read = reply->readAll(); QNetworkReply::NetworkError error = reply->error(); reply->deleteLater(); if(error) { qDebug() << "Terminal DB Error: Remote INI file not reachable: " << error; return; } else { if(read.isEmpty()) { qDebug() << "Terminal DB Error: Remote INI file response is empty:" << read; return; } qDebug() << "test3 - not empty"; QByteArray newFile = QCryptographicHash::hash(read, QCryptographicHash::Md5); QString fileName(QDir::currentPath() + "/" + settingsFile); QFile file(fileName); if(!file.open(QIODevice::ReadWrite)) { qDebug() << "Terminal DB Error: Creating local INI:" << file.error() << file.errorString(); return; } QByteArray oldFile = QCryptographicHash::hash(file.readAll(), QCryptographicHash::Md5); if (oldFile != newFile) { qDebug() << "Terminal DB: Downloading new INI file from remote source"; file.resize(0); file.write(read); } file.close(); refreshParameters(); } }
and basicaly the app debugs "test1" but then freezes all app till i see debug "test3 - not empty", so somehow it waits till the signal anynway? :(
-
@shokarta From the code you posted I don't see why it should freeze, but I don't know what else you are doing.