Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Application exits with exit code 0, when toBase64 is used



  • Good evening!

    Currently i'm working on a file upload and got stuck. Maybe someone with more experience in Qt 5 and C++ can help me out.

    The Application exits with exit code 0 before the Image is uploaded when toBase64 is used. This behavior does not occur when readAll is used.

    0_1543852859579_despair.gif

    fileio.h

    #ifndef FILEIO_H
    #define FILEIO_H
    
    #include <QObject>
    
    class FileIO : public QObject
    {
        Q_OBJECT
    
    public:
        explicit FileIO(QObject *parent = nullptr);
    
        Q_INVOKABLE QString read(const QString& Url);
        Q_INVOKABLE QString readBinaryAsBase64(const QString& Url);
        Q_INVOKABLE bool write(const QString& Url, QString data);
    
    
    public slots:
    
    signals:
        void error(const QString& msg);
    
    private:
        QString mSource;
    };
    
    #endif // FILEIO_H
    
    

    fileio.cpp

    #include "fileio.h"
    #include <QFile>
    #include <QTextStream>
    
    FileIO::FileIO(QObject *parent) :
        QObject(parent)
    {
    
    }
    
    QString FileIO::readBinaryAsBase64(const QString& Url)
    {
        mSource = Url;
        if (mSource.isEmpty()){
            emit error("source is empty");
            return QString();
        }
    
        QFile file(mSource);
        QString fileContent;
        if ( file.open(QIODevice::ReadOnly) ) {
            fileContent = QString::fromUtf8(file.readAll().toBase64(QByteArray::Base64UrlEncoding));
        } else {
            emit error("Unable to open the file");
            return QString();
        }
    
        return fileContent;
    }
    
    QString FileIO::read(const QString& Url)
    {
        mSource = Url;
        if (mSource.isEmpty()){
            emit error("source is empty");
            return QString();
        }
    
        QFile file(mSource);
        QString fileContent;
        if ( file.open(QIODevice::ReadOnly) ) {
            QString line;
            QTextStream t( &file );
            t.setCodec("UTF-8");
            do {
                line = t.readLine();
                fileContent += line;
             } while (!line.isNull());
    
            file.close();
        } else {
            emit error("Unable to open the file");
            return QString();
        }
    
        return fileContent;
    }
    
    bool FileIO::write(const QString& Url, QString data)
    {
        mSource = Url;
        if (mSource.isEmpty()){
            emit error("source is empty");
            return false;}
    
            QFile file(mSource);
            if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
                emit error("Error");
                return false;}
    
            QTextStream out(&file);
            out << data;
    
            file.close();
    
            return true;
    }
    
    

    main.cpp

    #include "fileio.h"
    #include <QGuiApplication>
    #include <QtWidgets/QApplication>
    #include <QQmlApplicationEngine>
    
    int main(int argc, char *argv[])
    {
        qmlRegisterType<FileIO, 1>("FileIO", 1, 0, "FileIO");
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        //QGuiApplication
        QApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    main.qml

    ApplicationWindow {
        visible: true
        width: 740
        height: 880
        title: qsTr("Test")
        Rectangle {
            property string oid: "123"
            id: rectPhoto
            anchors.fill: parent
            FileDialog {
                id: fileDialog
                title: "Please choose a file"
                folder: shortcuts.home
                onAccepted: {
                    console.log("You chose: " + fileDialog.fileUrls)
                    msgUpload.visible = true
                }
                onRejected: {
                    console.log("Canceled")
                }
            }
    
            MessageDialog {
                id: msgUpload
                title: "Upload?"
                icon: StandardIcon.Question
                text: "Do you really want to upload " + fileDialog.fileUrls + "?"
                standardButtons: StandardButton.Yes | StandardButton.No
                onYes: {
                    // removes "file://"
                    var path = fileDialog.fileUrls[0].slice(7)
                    var image = fileUpload.readBinaryAsBase64(path);
                    // works as expected
                    console.log("type", typeof image, "base64 data", image)
                    Employee.uploadPhoto(rectPhoto.oid, image, Utils.basename(path), function(http) {
                        if (http.readyState === 4) {
                            if (http.status === 200) {
                                console.log("ok");
                            } else {
                                console.log("error: " + http.status);
                            }
                        }
                    });
                }
            }
    
            FileIO {
                id: fileUpload
            }
    
            RowLayout {
                Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
            Button {
                text: "Upload!"
                id: btnUpload
                Layout.fillWidth: true
                onClicked: {
                    fileDialog.visible = true
    
                }
            }
            Button {
                text: Abort
                id: btnAbort
                Layout.fillWidth: true
            }
        }
    }
    

    employee.js

    function uploadPhoto(oid, image, image_name, callback) {
        var http = new XMLHttpRequest();
        var url = "http://localhost:8081/upload_photo";
        var params = "&image=" + image +
                    "&image_name=" + encodeURIComponent(image_name) +
                    "&oid=" + encodeURIComponent(oid);
        http.open("POST", url, true);
    
        // Send the proper header information along with the request
        http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        http.setRequestHeader("Content-length", params.length);
        http.setRequestHeader("Connection", "close");
    
        http.onreadystatechange = function() { // Call a function when the state changes.
            callback(http);
        }
        http.send(params);
    }
    

    utils.js

    function basename(str, sep) {
        return str.substr(str.lastIndexOf(sep) + 1);
    }
    

    Kind Regards,

    GrrArgh


  • Qt Champions 2017

    I'm assuming that you are just uploading the image. It should be just uploaded without any encoding. Any idea why r u encoding to base64 with URLEncoding ?

    As added noted, It can done with backend C++ code itself rather than doing this in QML and moving around the image between C++ and QML.


  • Lifetime Qt Champion

    Hi,

    First thing to do: stop using QString when dealing with binary content, use QByteArray. Base64 encoded data can be stored in a QString because the binary data is encoded in a string representation. However loading the content of a non-text file in a QString will definitely get you in trouble since the data will "stop" at the first termination character it crosses.



  • @SGaist said in Application exits with exit code 0, when toBase64 is used:

    Hi,

    First thing to do: stop using QString when dealing with binary content, use QByteArray. Base64 encoded data can be stored in a QString because the binary data is encoded in a string representation. However loading the content of a non-text file in a QString will definitely get you in trouble since the data will "stop" at the first termination character it crosses.

    Thanks, I know that. I only posted the solution depending on Base64 encoding and not the whole. I just wanna figure out why this implementation is behaving like explained.

    The same sample, modified to transfer binary an image does work.


Log in to reply