使用 NetworkManager 上传文件不起作用
Posted
技术标签:
【中文标题】使用 NetworkManager 上传文件不起作用【英文标题】:Upload files using QNetworkManager is not woking 【发布时间】:2021-05-15 23:16:10 【问题描述】:所以我正在尝试使用 Qt Network Manager 将一个简单的文本文件上传到我正在服务的 php 脚本中。但它不起作用。我尝试了使用 QHttpMultiPart 和在请求中设置原始数据标头的示例,但没有任何效果。
这是我的 Qt 代码:
#include <QCoreApplication>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QDebug>
#include <QEventLoop>
#include <QObject>
#include <QVariantMap>
#include <QJsonDocument>
#include <QFile>
#include <QHttpMultiPart>
int main(int argc, char *argv[])
QCoreApplication a(argc, argv);
QString address = "http://localhost/api_test/";
//address = "https://dashboard.viewmind.ai/dashboard/api_test/welcome.php";
QUrl api_url = QUrl(address);
QVariantMap postDatamap;
postDatamap.insert("Name","Ariel Ñoño");
postDatamap.insert("Age",37);
QJsonDocument json = QJsonDocument::fromVariant(postDatamap);
qDebug() << "Sending the request";
QNetworkAccessManager *networkManager = new QNetworkAccessManager();
QNetworkRequest request(api_url);
QString bound = "<<<<<boundary>>>>>";
request.setRawHeader(QString("Content-Type").toUtf8(),QString("multipart/form-postData; boundary=" + bound).toUtf8());
//QByteArray postData;
QByteArray postData(QString("--" + bound + "\r\n").toUtf8());
postData.append("Content-Disposition: form-postData; name=\"action\"\r\n\r\n");
postData.append("welcome.php\r\n");
postData.append(QString("--" + bound + "\r\n").toUtf8());
postData.append("Content-Disposition: form-postData; name=\"uploaded\"; filename=\"");
postData.append("test.json");
postData.append("\"\r\n");
postData.append("Content-Type: text/xml\r\n\r\n"); //postData type
QFile file("test.json");
if (!file.open(QIODevice::ReadOnly))
qDebug() << "QFile Error: File not found!";
delete networkManager;
return 0;
else qDebug() << "File found, proceed as planned";
postData.append(file.readAll());
postData.append("\r\n");
postData.append(QString("--" + bound + "\r\n").toUtf8());
request.setRawHeader(QString("Content-Length").toUtf8(), QString::number(postData.length()).toUtf8());
//request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json; charset=utf-8");
//request.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-postData; name=\"text\""));
//qDebug() << QString(json.toJson());
//QHttpMultiPart multipart(QHttpMultiPart::FormDataType);
//QHttpPart textPart;
// QFile file("test.json");
// if (!file.open(QIODevice::ReadOnly))
// qDebug() << "Could not open file for reading";
// delete networkManager;
// return 0;
//
//textPart.setBodyDevice(&file);
//multipart.append(textPart);
//file.setParent(&multipart);
//QNetworkReply *reply = networkManager->post(request,json.toJson());
//QNetworkReply *reply = networkManager->post(request,file.readAll());
//QNetworkReply *reply = networkManager->post(request,&multipart);
QNetworkReply *reply = networkManager->post(request,postData);
//file.setParent(reply);
//multipart.setParent(reply);
// Using the loop to wait for the reply to finish.
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
qDebug() << "Reply is finished";
//file.close();
if (reply->error() != QNetworkReply::NoError)
qDebug() << "The following error ocurred";
qDebug() << reply->errorString();
return 0;
QString postData_returned = QString::fromUtf8(reply->readAll());
qDebug() << "DATA RETURNED";
qDebug() << postData_returned;
return 0;
我的 php 代码是这样的
<?php
header("Access-Control-Allow-Origin: *"); // Anyone can access
header("Content-Type: application/json; charset=UTF-8"); // Will return json data.
error_log("FILES iS");
vardump_toerror($_FILES);
?>
我的理解是 $_FILES 超级全局应该填充文件信息。我弄错了吗?但是打印出来的显示是空的。
【问题讨论】:
【参考方案1】:我不是 PHP 专家,但我发现没有必要使用内容类型 application/json,因为 multipart(提交表单)不是该协议的一部分。另一方面,我找不到vardump_toerror
函数的引用,所以我用var_dump
更改所以我的测试php 是:
<?php
var_dump($_FILES);
?>
在 PyQt5 的 previous question 中,我为 django 实现了类似的逻辑,该逻辑也适用于这种情况,因此我将显示翻译。
#include <QCoreApplication>
#include <QFile>
#include <QHttpMultiPart>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTextCodec>
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);
QUrl url("http://localhost:4000/upload.php");
QNetworkAccessManager manager;
QMap<QString, QString> filenames;
filenames["fileToUpload"] = "/path/of/data.txt";
QHttpMultiPart *multipart = buildMultpart(, filenames);
QNetworkRequest request(url);
QNetworkReply *reply = manager.post(request, multipart);
multipart->setParent(reply);
QObject::connect(reply, &QNetworkReply::finished, QCoreApplication::quit);
a.exec();
if(reply->error() == QNetworkReply::NoError)
qDebug() << reply->readAll();
else
qDebug() << reply->error() << reply->errorString();
delete reply;
return 0;
输出:
"array(1) \n [\"fileToUpload\"]=>\n array(5) \n [\"name\"]=>\n string(8) \"data.txt\"\n [\"type\"]=>\n string(0) \"\"\n [\"tmp_name\"]=>\n string(14) \"/tmp/phpVmOAhO\"\n [\"error\"]=>\n int(0)\n [\"size\"]=>\n int(6)\n \n\n"
【讨论】:
你是男人!!!像魅力一样工作。抱歉 vardump_toerror。它只是一个将变量转储到字符串并将变量转储到错误日志的函数。我使用了您的代码原样并且它有效。我要弄清楚我和我的区别是什么。谢谢!!!以上是关于使用 NetworkManager 上传文件不起作用的主要内容,如果未能解决你的问题,请参考以下文章
我的Android进阶之旅------>Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法
如何在用户离线时尝试将数据添加/上传到 Firebase 时显示错误?