Home > Net >  Post a form with QT
Post a form with QT

Time:11-17

I am working with a team on a C project using Qt. As part of our project, we have to be able to retrieve coordinates of any given address in France. The French government provivdes an API that handles that for us.

The call to the API looks like this:

curl -X POST -F data=@path/to/file.csv https://api-adresse.data.gouv.fr/search/csv/

Here is the code I wrote:

int main (int argc, char* argv[]){
    QCoreApplication app(argc, argv);
    QNetworkAccessManager man;

    QUrl url("https://api-adresse.data.gouv.fr/search/csv/");
    QNetworkRequest req(url);

    QFile inputFile("<path_to_search.csv>");
    inputFile.open(QIODevice::ReadOnly);
    QByteArray data = inputFile.readAll();

    QNetworkReply* reply = man.post(req, "data="   data);
    QObject::connect(reply, &QNetworkReply::finished, [&](){
            QByteArray read = reply->readAll();
            std::cout << "Reading Data:" << std::endl;
            std::cout << read.toStdString() << std::endl;
            reply->close();
            reply->deleteLater();
            app.quit();
    });
    return app.exec();
}

The server replies with

{"code":400,"message":"A CSV file must be provided in data field"}

So clearly I am forwarding the form incorrectly. How should I proceed?

CodePudding user response:

To send information through the forms, I don't know the query section, but rather you want to use QHttpMultiPart as I show in this old post. Applying to your case the solution is:

#include <QCoreApplication>
#include <QFile>
#include <QHttpMultiPart>
#include <QNetworkAccessManager>
#include <QNetworkReply>

QHttpMultiPart *buildMultpart(const QVariantMap & data, const QMap<QString, QString> filenames){

    QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    QVariantMap::const_iterator i_data = data.constBegin();
    while (i_data != data.constEnd()) {
        QHttpPart postpart;
        postpart.setHeader(QNetworkRequest::ContentDispositionHeader, QString("form-data; name=\"%1\"").arg(i_data.key()));
        postpart.setBody(i_data.value().toByteArray());
        multipart->append(postpart);
          i_data;
    }
    QMap<QString, QString>::const_iterator i_filenames = filenames.constBegin();
    while (i_filenames != filenames.constEnd()) {

        QFile *file = new QFile(i_filenames.value());
        if(!file->open(QIODevice::ReadOnly)){
            delete  file;
            continue;
        }
        QHttpPart postpart;
        postpart.setHeader(QNetworkRequest::ContentDispositionHeader,
                           QString("form-data; name=\"%1\"; filename=\"%2\"")
                           .arg(i_filenames.key(), file->fileName()));
        postpart.setBodyDevice(file);
        multipart->append(postpart);
        file->setParent(multipart);
          i_filenames;
    }
    return multipart;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QNetworkAccessManager manager;

    QNetworkRequest request;
    QUrl url("https://api-adresse.data.gouv.fr/search/csv/");
    request.setUrl(url);
    QMap<QString, QString> filenames;
    filenames["data"] = "/path/of/file.csv";
    QHttpMultiPart *multipart = buildMultpart({}, filenames);
    QNetworkReply *reply = manager.post(request, multipart);
    multipart->setParent(reply);
    QObject::connect(reply, &QNetworkReply::finished, [reply](){
        if(reply->error() == QNetworkReply::NoError){
            qDebug().noquote() << reply->readAll();
        }
        else{
            qDebug() << reply->error() << reply->errorString();
        }
        reply->deleteLater();
        QCoreApplication::quit();
    });
    return a.exec();
}
  • Related