Home > Mobile >  Uploading chunk of file to server with post request. Qt6 QNetworkAccessManager post. Data not arriev
Uploading chunk of file to server with post request. Qt6 QNetworkAccessManager post. Data not arriev

Time:05-18

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

CodePudding user response:

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();
}
  • Related