QNetworkAccessManager check if file exists
-
Hi all
I upload a file using ftp to a destination. That works fine.
Now I try to check before upöoad, if the file already exists.
I found the hint that it shold work with NetworkAccessManager->head(request) and read the request->error().
I do it like this:if(QuellFile->open(QIODevice::ReadWrite)){ QNetworkReply *reply = NetworkAccessManager->head(request); qDebug() << reply->error(); if (reply->error() == QNetworkReply::NoError){ reply = NetworkAccessManager->put(request, QuellFile->readAll()); connect(reply, &QNetworkReply::uploadProgress, this, &MainWindow::uploadProgress); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64,qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError))); meldung("File uploaded."); }else{ ConfirmDialog dialog("File already exists. Replace?"); dialog.exec(); if (dialog.getResult()){ reply = NetworkAccessManager->put(request, QuellFile->readAll()); connect(reply, &QNetworkReply::uploadProgress, this, &MainWindow::uploadProgress); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64,qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError))); meldung("File was replaced."); }else{ meldung("File was not replaced"); } } }
No matter if the file is already exising or not, the reply->error() returns QNetworkReply::NoError.
What am I doing wrong?Thanks in advance,
Thomas@Thomas-63 This is the response I get from a trivial test case:
#include <QCoreApplication> #include <QDebug> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> #include <QObject> #include <QTimer> class Test : public QObject { Q_OBJECT public: explicit Test(QObject *p = nullptr) : QObject(p) , m_nam(new QNetworkAccessManager(this)) { connect(m_nam, &QNetworkAccessManager::finished, this, &Test::receiveReply); // does exist m_nam->get(QNetworkRequest(QUrl("ftp://test.rebex.net/readme.txt"))); // does not exist m_nam->get(QNetworkRequest(QUrl("ftp://test.rebex.net/missing.txt"))); } public slots: void receiveReply(QNetworkReply *reply) { qDebug() << reply << reply->error() << reply->request().url() << reply->header(QNetworkRequest::ContentLengthHeader) << reply->header(QNetworkRequest::LastModifiedHeader); reply->deleteLater(); } private: QNetworkAccessManager *m_nam; }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); QTimer::singleShot(10000, &app, &QCoreApplication::quit); Test t; return app.exec(); } #include "main.moc"
15:40:37: Starting /tmp/test/build/Ubuntu_5_15-Debug/test... QNetworkReplyImpl(0x5950736b2900) QNetworkReply::NoError QUrl("ftp://test.rebex.net/readme.txt") QVariant(qlonglong, 379) QVariant(QDateTime, QDateTime(2023-09-19 11:12:03.000 AEST Qt::LocalTime)) QNetworkReplyImpl(0x59507376f3f0) QNetworkReply::ContentNotFoundError QUrl("ftp://test.rebex.net/missing.txt") QVariant(Invalid) QVariant(Invalid)
I have no FTP support in Qt 6 to test with.
-
@Thomas-63 This is the response I get from a trivial test case:
#include <QCoreApplication> #include <QDebug> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> #include <QObject> #include <QTimer> class Test : public QObject { Q_OBJECT public: explicit Test(QObject *p = nullptr) : QObject(p) , m_nam(new QNetworkAccessManager(this)) { connect(m_nam, &QNetworkAccessManager::finished, this, &Test::receiveReply); // does exist m_nam->get(QNetworkRequest(QUrl("ftp://test.rebex.net/readme.txt"))); // does not exist m_nam->get(QNetworkRequest(QUrl("ftp://test.rebex.net/missing.txt"))); } public slots: void receiveReply(QNetworkReply *reply) { qDebug() << reply << reply->error() << reply->request().url() << reply->header(QNetworkRequest::ContentLengthHeader) << reply->header(QNetworkRequest::LastModifiedHeader); reply->deleteLater(); } private: QNetworkAccessManager *m_nam; }; int main(int argc, char **argv) { QCoreApplication app(argc, argv); QTimer::singleShot(10000, &app, &QCoreApplication::quit); Test t; return app.exec(); } #include "main.moc"
15:40:37: Starting /tmp/test/build/Ubuntu_5_15-Debug/test... QNetworkReplyImpl(0x5950736b2900) QNetworkReply::NoError QUrl("ftp://test.rebex.net/readme.txt") QVariant(qlonglong, 379) QVariant(QDateTime, QDateTime(2023-09-19 11:12:03.000 AEST Qt::LocalTime)) QNetworkReplyImpl(0x59507376f3f0) QNetworkReply::ContentNotFoundError QUrl("ftp://test.rebex.net/missing.txt") QVariant(Invalid) QVariant(Invalid)
I have no FTP support in Qt 6 to test with.
@ChrisW67 Hi and thanks for the hints.
I use this code now:
QNetworkRequest request(url); QNetworkReply *reply = NetworkAccessManager->get(request); qDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader); if(QuellFile->open(QIODevice::ReadWrite)){ if (reply->error() != QNetworkReply::ContentNotFoundError){ ConfirmDialog dialog("File exists. Overwrite?"); if (dialog.getResult()){ reply = NetworkAccessManager->put(request, QuellFile->readAll()); connect(reply, &QNetworkReply::uploadProgress, this, &MainWindow::uploadProgress); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64,qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError))); meldung("File replaced"); }else{ meldung("File not replaced."); } } }
qDebug() gives me:
QNetworkReplyImpl(0x6f30350) QNetworkReply::NoError QUrl("ftp://user@ftpserver.ch:21/dokumentation/1_1_1.pdf") QVariant(Invalid) QVariant(Invalid)
-
@ChrisW67 Hi and thanks for the hints.
I use this code now:
QNetworkRequest request(url); QNetworkReply *reply = NetworkAccessManager->get(request); qDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader); if(QuellFile->open(QIODevice::ReadWrite)){ if (reply->error() != QNetworkReply::ContentNotFoundError){ ConfirmDialog dialog("File exists. Overwrite?"); if (dialog.getResult()){ reply = NetworkAccessManager->put(request, QuellFile->readAll()); connect(reply, &QNetworkReply::uploadProgress, this, &MainWindow::uploadProgress); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64,qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError))); meldung("File replaced"); }else{ meldung("File not replaced."); } } }
qDebug() gives me:
QNetworkReplyImpl(0x6f30350) QNetworkReply::NoError QUrl("ftp://user@ftpserver.ch:21/dokumentation/1_1_1.pdf") QVariant(Invalid) QVariant(Invalid)
@Thomas-63 Not sure what you're trying to do with your code.
@ChrisW67 gave you code which is working - did you try it?Just as a tip: you should switch to Qt5 connect() syntax.
-
@Thomas-63 Not sure what you're trying to do with your code.
@ChrisW67 gave you code which is working - did you try it?Just as a tip: you should switch to Qt5 connect() syntax.
QNetworkRequest request(url); //url is the complete path/name of the destination file i want to write. QNetworkReply *reply = NetworkAccessManager->get(request); qDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader); if(QuellFile->open(QIODevice::ReadWrite)){ // QuellFile is the resource file on my drive if (reply->error() != QNetworkReply::ContentNotFoundError){ //when file does not exist ConfirmDialog dialog("File exists. Overwrite?"); // ask whether to overwrite (this dialog does not show) if (dialog.getResult()){ // response to dialog reply = NetworkAccessManager->put(request, QuellFile->readAll()); // upload file connect(reply, &QNetworkReply::uploadProgress, this, &MainWindow::uploadProgress); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64,qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError))); meldung("File replaced"); }else{ meldung("File not replaced."); // strangely this message is shown all the time } } }
-
QNetworkRequest request(url); //url is the complete path/name of the destination file i want to write. QNetworkReply *reply = NetworkAccessManager->get(request); qDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader); if(QuellFile->open(QIODevice::ReadWrite)){ // QuellFile is the resource file on my drive if (reply->error() != QNetworkReply::ContentNotFoundError){ //when file does not exist ConfirmDialog dialog("File exists. Overwrite?"); // ask whether to overwrite (this dialog does not show) if (dialog.getResult()){ // response to dialog reply = NetworkAccessManager->put(request, QuellFile->readAll()); // upload file connect(reply, &QNetworkReply::uploadProgress, this, &MainWindow::uploadProgress); connect(reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64,qint64))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(loadError(QNetworkReply::NetworkError))); meldung("File replaced"); }else{ meldung("File not replaced."); // strangely this message is shown all the time } } }
@Thomas-63 said in QNetworkAccessManager check if file exists:
}else{ meldung("File not replaced."); // strangely this message is shown all the time }
If this message is shown all the time it is an
else
to yourif (dialog.getResult()){ // response to dialog
so how does that have anything to do with network or file transfer??
Start by getting rid of your dialog code, you are supposed to produce a small example of the problem.
-
@Thomas-63 said in QNetworkAccessManager check if file exists:
}else{ meldung("File not replaced."); // strangely this message is shown all the time }
If this message is shown all the time it is an
else
to yourif (dialog.getResult()){ // response to dialog
so how does that have anything to do with network or file transfer??
Start by getting rid of your dialog code, you are supposed to produce a small example of the problem.
-
@JonB
Why does the blockqDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader);
give me QVariant(Invalid) QVariant(Invalid) for the header() - parts?
Why does the block
qDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader);
give me QVariant(Invalid) QVariant(Invalid) for the header() - parts?
In the position you have this in your code the GET request has not been sent and thus the reply object has not yet been populated i.e., nothing to display. Qt networking is, by default, asynchronous. The request will not be sent until the Qt event loop is reached. You need to reorganise your code to handle the async nature of Qt networking.
BTW, why a GET and not a HEAD?
I tried your example site in my code and got:
QNetworkReplyImpl(0x5a7cc54c6120) QNetworkReply::ConnectionRefusedError QUrl("ftp://user@ftpserver.ch:21/dokumentation/1_1_1.pdf") QVariant(Invalid) QVariant(Invalid)
You have not shared if my code ran as-is on your system.
-
Why does the block
qDebug() << reply << reply->error() << reply->request().url() << reply->header(request.ContentLengthHeader) << reply->header(request.LastModifiedHeader);
give me QVariant(Invalid) QVariant(Invalid) for the header() - parts?
In the position you have this in your code the GET request has not been sent and thus the reply object has not yet been populated i.e., nothing to display. Qt networking is, by default, asynchronous. The request will not be sent until the Qt event loop is reached. You need to reorganise your code to handle the async nature of Qt networking.
BTW, why a GET and not a HEAD?
I tried your example site in my code and got:
QNetworkReplyImpl(0x5a7cc54c6120) QNetworkReply::ConnectionRefusedError QUrl("ftp://user@ftpserver.ch:21/dokumentation/1_1_1.pdf") QVariant(Invalid) QVariant(Invalid)
You have not shared if my code ran as-is on your system.
Something along these lines might work (untested):
class Uploader : public QObject { Q_OBJECT public: explicit Uploader(QObject *p = nullptr) : QObject(p) , m_nam(new QNetworkAccessManager(this)) { } void upload(const QUrl& target, const QString &file) { m_target = target; m_file = file; QNetworkReply *headReply = m_nam->head(QNetworkRequest(m_target)); connect(headReply, &QNetworkReply::finished, this, &Uploader::receiveHeadReply); // connect error signals etc... } public slots: void receiveHeadReply(QNetworkReply *reply) { qDebug() << Q_FUNC_INFO << reply->error() << reply->request().url() << reply->header(QNetworkRequest::ContentLengthHeader) << reply->header(QNetworkRequest::LastModifiedHeader); bool upload = false; if (reply->error() == QNetworkReply::NoError) { // file exists // prompt for overwrite // if yes then upload = true; } else if (reply->error() == QNetworkReply::ContentNotFoundError) { qDebug() << "Not there so we can upload"; upload = true; } else { // some other error condition we need to handle or ignore } reply->deleteLater(); if (upload) { // open m_file, read data, send data QByteArray data; QNetworkReply *putReply = m_nam->put(QNetworkRequest(m_target), data); connect(putReply, &QNetworkReply::finished, this, &Uploader::receivePutReply); } } void receivePutReply(QNetworkReply *reply) { qDebug() << Q_FUNC_INFO << reply->error() << reply->request().url(); reply->deleteLater(); } private: QNetworkAccessManager *m_nam; QUrl m_target; QString m_file; };