Post一个QT表格
Post a form with QT
我正在与一个使用 Qt 的 C++ 项目团队合作。作为我们项目的一部分,我们必须能够检索法国任何给定地址的坐标。法国政府提供了一个 API 来为我们处理这个问题。
对 API 的调用如下所示:
curl -X POST -F data=@path/to/file.csv https://api-adresse.data.gouv.fr/search/csv/
这是我写的代码:
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();
}
服务器回复
{"code":400,"message":"A CSV file must be provided in data field"}
很明显我转发的表格不正确。我该如何进行?
要通过表单发送信息,我不知道查询部分,但你想使用 QHttpMultiPart,正如我在此 中展示的那样。适用于您的情况的解决方案是:
#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();
}
我正在与一个使用 Qt 的 C++ 项目团队合作。作为我们项目的一部分,我们必须能够检索法国任何给定地址的坐标。法国政府提供了一个 API 来为我们处理这个问题。
对 API 的调用如下所示:
curl -X POST -F data=@path/to/file.csv https://api-adresse.data.gouv.fr/search/csv/
这是我写的代码:
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();
}
服务器回复
{"code":400,"message":"A CSV file must be provided in data field"}
很明显我转发的表格不正确。我该如何进行?
要通过表单发送信息,我不知道查询部分,但你想使用 QHttpMultiPart,正如我在此
#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();
}