通过发布请求将文件块上传到服务器。 QT6 QNETWORKACCESSMANAGER帖子。数据未能到达

发布于 2025-01-29 09:35:50 字数 5396 浏览 2 评论 0原文

我正在尝试移植我的程序(Python(pyqt6)>> c ++(qt6)) 在Python中,我有一个:

requests.post(f"{self.server}/uploadChunk/{self.rnum}?" + urlencode(
                            {"index": cnum, "findex": findex, "token": self.token, "Hash": out_hash}),
                                      data=chunk, verify=False)

我正在尝试将其移植到C ++并获得此信息:

void Tunnel::sendChunk(quint64 findex, quint64 index, QByteArray chunk, QString hash) {
    qDebug() << "T: sendChunk";
    TunnelWorker *worker = (TunnelWorker*)this->sender();
    quint64 id = worker->Id;
    QNetworkAccessManager *manager = (*this->Managers)[id][1];
    QString url = this->server + "/uploadChunk/" + QString::number(this->rnum) + "?token=" + this->token;
    if ((int)index != -1) {
        url += "&findex=" + QString::number(findex) + "&index=" + QString::number(index) + "&hash=" + hash;
    }
    QNetworkRequest req = QNetworkRequest(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
    QNetworkReply *reply = manager->post(req, chunk);
    QObject::connect(reply, &QNetworkReply::uploadProgress, worker, &TunnelWorker::sendChunkProgressHandler);
}

在控制台中,我看到该文件正在上传::

TW: sendChunkProgressHandler
T: addUploadProgress "16384"
TW: sendChunkProgressHandler
T: addUploadProgress "2080768"
TW: sendChunkProgressHandler
TW: sendChunkReplyHandler: chunk uploaded
T: addUploadProgress "0"

我的块size是2Mib,(2 ** 21字节),我看到所有2MIB上传。 我在烧瓶上有我的服务器:

class Tunnel:
    ...
    def downloadchunk(self, data, json):
        print('-' * 20)
        print(f"DATA: {len(data)}")
        print('-' * 20)
        ...
    ...
# end of class Tunnel
...
@app.route("/uploadChunk/<int:rnum>", methods=['GET', 'POST'])
def upload_chunk(rnum):
    json = request.args
    token = "00000000" if "token" not in json else json["token"]
    if checkToken(rnum, "Up", token):
        rnums[rnum].activity()
        data = request.data
        return rnums[rnum].downloadchunk(data, json)
    else:
        return {"status": "Access denied"}
...

如果我尝试了我的C ++代码,我会在烧瓶服务器的Python控制台中获取此信息:

--------------------
DATA: 0
--------------------

我尝试了我的python代码,我会得到这个...:

--------------------
DATA: 2097152
--------------------

如果 我的C ++代码?

UDP 最小可重复的例子: main.cpp

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

int main(int argc, char *argv[])
{
    quint64 Kb = 1024;
    quint64 Mb = 1024 * Kb;
    QCoreApplication a(argc, argv);
    QFile file("img.png");
    file.open(QFile::ReadOnly);
    QByteArray chunk = file.read(2 * Mb);
    qDebug() << "Chunk:" << chunk.length();
    QNetworkAccessManager *manager = new QNetworkAccessManager();
    QUrl url = QUrl("http://127.0.0.1:5000/");
    QNetworkRequest req = QNetworkRequest(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
    qDebug() << "Url:" << url.url();
    QObject::connect(manager, &QNetworkAccessManager::finished, [](QNetworkReply *reply) {qDebug() << "Uploading Finish";});
    QNetworkReply *reply = manager->post(req, chunk);
    QObject::connect(reply, &QNetworkReply::uploadProgress, [](quint64 uploaded, quint64 total) {qDebug() << "Uploading" << QString::number(uploaded) << "/" << QString::number(total);});
    return a.exec();
}

test.pro:server.py:udp2

QT -= gui
QT += core
QT += network

CONFIG += c++17 console
CONFIG -= app_bundle

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

from flask import Flask, request


app = Flask(__name__)


@app.route("/", methods=["GET", "POST"])
def fun():
    print("DATA:", len(request.data))
    return {}


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

​ 我的控制台输出(C ++):

Chunk: 2097152
Url: "http://127.0.0.1:5000/"
Uploading "16384" / "2097152"
Uploading "2097152" / "2097152"
Uploading "0" / "0"
Uploading Finish

我的控制台输出(Python):

 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Serving Flask app 'SOF.py' (lazy loading)
 * Environment: development
 * Debug mode: off
127.0.0.1 - - [17/May/2022 15:13:02] "POST / HTTP/1.1" 200 -
DATA: 0

UDP3: test.py

import requests

with open("img.png", "rb") as f:
    data = f.read(2*1024*1024)
    requests.post("http://127.0.0.1:5000/", data=data)

server.py(输出):

 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Serving Flask app 'SOF.py' (lazy loading)
 * Environment: development
 * Debug mode: off
127.0.0.1 - - [17/May/2022 15:31:01] "POST / HTTP/1.1" 200 -
DATA: 2097152

i'm trying to port my program (python(PyQt6) >> C++(Qt6))
In python i have this:

requests.post(f"{self.server}/uploadChunk/{self.rnum}?" + urlencode(
                            {"index": cnum, "findex": findex, "token": self.token, "Hash": out_hash}),
                                      data=chunk, verify=False)

I'm trying to port it to C++ and get this:

void Tunnel::sendChunk(quint64 findex, quint64 index, QByteArray chunk, QString hash) {
    qDebug() << "T: sendChunk";
    TunnelWorker *worker = (TunnelWorker*)this->sender();
    quint64 id = worker->Id;
    QNetworkAccessManager *manager = (*this->Managers)[id][1];
    QString url = this->server + "/uploadChunk/" + QString::number(this->rnum) + "?token=" + this->token;
    if ((int)index != -1) {
        url += "&findex=" + QString::number(findex) + "&index=" + QString::number(index) + "&hash=" + hash;
    }
    QNetworkRequest req = QNetworkRequest(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
    QNetworkReply *reply = manager->post(req, chunk);
    QObject::connect(reply, &QNetworkReply::uploadProgress, worker, &TunnelWorker::sendChunkProgressHandler);
}

In console, i see that file is uploading:

TW: sendChunkProgressHandler
T: addUploadProgress "16384"
TW: sendChunkProgressHandler
T: addUploadProgress "2080768"
TW: sendChunkProgressHandler
TW: sendChunkReplyHandler: chunk uploaded
T: addUploadProgress "0"

: My Chunksize is 2MiB, (2**21 Bytes), i see that all 2MiB uploaded.
I have my server on Flask:

class Tunnel:
    ...
    def downloadchunk(self, data, json):
        print('-' * 20)
        print(f"DATA: {len(data)}")
        print('-' * 20)
        ...
    ...
# end of class Tunnel
...
@app.route("/uploadChunk/<int:rnum>", methods=['GET', 'POST'])
def upload_chunk(rnum):
    json = request.args
    token = "00000000" if "token" not in json else json["token"]
    if checkToken(rnum, "Up", token):
        rnums[rnum].activity()
        data = request.data
        return rnums[rnum].downloadchunk(data, json)
    else:
        return {"status": "Access denied"}
...

If i'm trying my C++ code, i get this in python console of my flask server:

--------------------
DATA: 0
--------------------

If i'm trying my python code, i get this...:

--------------------
DATA: 2097152
--------------------

That i need to fix uploading in my c++ code?

UDP minimal reproducible example:
main.cpp

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

int main(int argc, char *argv[])
{
    quint64 Kb = 1024;
    quint64 Mb = 1024 * Kb;
    QCoreApplication a(argc, argv);
    QFile file("img.png");
    file.open(QFile::ReadOnly);
    QByteArray chunk = file.read(2 * Mb);
    qDebug() << "Chunk:" << chunk.length();
    QNetworkAccessManager *manager = new QNetworkAccessManager();
    QUrl url = QUrl("http://127.0.0.1:5000/");
    QNetworkRequest req = QNetworkRequest(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
    qDebug() << "Url:" << url.url();
    QObject::connect(manager, &QNetworkAccessManager::finished, [](QNetworkReply *reply) {qDebug() << "Uploading Finish";});
    QNetworkReply *reply = manager->post(req, chunk);
    QObject::connect(reply, &QNetworkReply::uploadProgress, [](quint64 uploaded, quint64 total) {qDebug() << "Uploading" << QString::number(uploaded) << "/" << QString::number(total);});
    return a.exec();
}

test.pro:

QT -= gui
QT += core
QT += network

CONFIG += c++17 console
CONFIG -= app_bundle

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp

# Default rules for deployment.
qnx: target.path = /tmp/${TARGET}/bin
else: unix:!android: target.path = /opt/${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

server.py:

from flask import Flask, request


app = Flask(__name__)


@app.route("/", methods=["GET", "POST"])
def fun():
    print("DATA:", len(request.data))
    return {}


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

UDP2:
My console output(C++):

Chunk: 2097152
Url: "http://127.0.0.1:5000/"
Uploading "16384" / "2097152"
Uploading "2097152" / "2097152"
Uploading "0" / "0"
Uploading Finish

My console output(Python):

 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Serving Flask app 'SOF.py' (lazy loading)
 * Environment: development
 * Debug mode: off
127.0.0.1 - - [17/May/2022 15:13:02] "POST / HTTP/1.1" 200 -
DATA: 0

UDP3:
test.py

import requests

with open("img.png", "rb") as f:
    data = f.read(2*1024*1024)
    requests.post("http://127.0.0.1:5000/", data=data)

server.py(Output):

 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Serving Flask app 'SOF.py' (lazy loading)
 * Environment: development
 * Debug mode: off
127.0.0.1 - - [17/May/2022 15:31:01] "POST / HTTP/1.1" 200 -
DATA: 2097152

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对你而言 2025-02-05 09:35:50

问题在于您指出内容类型是应用程序/x-www-form-urlenCoded(它等效于Multipart/form-data),但是您不是发送表单,而是发送形式,而是原始数据,因此服务器试图解码数据但不符合标准,因此它返回0字节。解决方案是使用有效的内容类型,例如Application/Octet-Stream,您还可以使用Qmimedatabase获取内容类型:

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

#include <QMimeDatabase>
#include <QMimeType>

int main(int argc, char *argv[])
{
    quint64 Kb = 1024;
    quint64 Mb = 1024 * Kb;
    QCoreApplication a(argc, argv);
    QFile file("img.png");
    if(!file.open(QFile::ReadOnly)){
        qDebug() << "failed";
        return EXIT_FAILURE;
    }
    QByteArray chunk = file.read(2 * Mb);
    qDebug() << "Chunk:" << chunk.length();
    QNetworkAccessManager manager;
    QUrl url = QUrl("http://127.0.0.1:5000/");
    
    QMimeDatabase db;
    QMimeType mime = db.mimeTypeForData(&file);

    QNetworkRequest req(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, mime.name());
    // OR
    // req.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");

    qDebug() << "Url:" << req.url();
    QObject::connect(&manager, &QNetworkAccessManager::finished, [](QNetworkReply * /*reply*/) {
        qDebug() << "Uploading Finish";
        QCoreApplication::quit();
    });
    QNetworkReply *reply = manager.post(req, chunk);
    QObject::connect(reply, &QNetworkReply::uploadProgress, [](quint64 uploaded, quint64 total) {
        qDebug() << "Uploading" << QString::number(uploaded) << "/" << QString::number(total);
    });
    return a.exec();
}

The problem is that you are indicating that the content-type is application/x-www-form-urlencoded (it is equivalent to multipart/form-data) but you are not sending a form but raw data so the server tries to decode the data but it does not meet the standard so it returns 0 bytes. The solution is to use a valid content-type, for example application/octet-stream, you can also use QMimeDatabase to get the content-type:

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

#include <QMimeDatabase>
#include <QMimeType>

int main(int argc, char *argv[])
{
    quint64 Kb = 1024;
    quint64 Mb = 1024 * Kb;
    QCoreApplication a(argc, argv);
    QFile file("img.png");
    if(!file.open(QFile::ReadOnly)){
        qDebug() << "failed";
        return EXIT_FAILURE;
    }
    QByteArray chunk = file.read(2 * Mb);
    qDebug() << "Chunk:" << chunk.length();
    QNetworkAccessManager manager;
    QUrl url = QUrl("http://127.0.0.1:5000/");
    
    QMimeDatabase db;
    QMimeType mime = db.mimeTypeForData(&file);

    QNetworkRequest req(url);
    req.setHeader(QNetworkRequest::ContentTypeHeader, mime.name());
    // OR
    // req.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");

    qDebug() << "Url:" << req.url();
    QObject::connect(&manager, &QNetworkAccessManager::finished, [](QNetworkReply * /*reply*/) {
        qDebug() << "Uploading Finish";
        QCoreApplication::quit();
    });
    QNetworkReply *reply = manager.post(req, chunk);
    QObject::connect(reply, &QNetworkReply::uploadProgress, [](quint64 uploaded, quint64 total) {
        qDebug() << "Uploading" << QString::number(uploaded) << "/" << QString::number(total);
    });
    return a.exec();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文