Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED]How send binary file to Postgres server?
Forum Updated to NodeBB v4.3 + New Features

[SOLVED]How send binary file to Postgres server?

Scheduled Pinned Locked Moved General and Desktop
33 Posts 5 Posters 18.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • freddy311082F Offline
    freddy311082F Offline
    freddy311082
    wrote on last edited by
    #4

    Thank for answer JKSH and sorry for the code... I didn't know about @.

    I just need the binary data from file in a QString.... is that possible ?

    I had open an xlsx file as example, but I need to do this with any kinf of files: PDF, JPEG, PNG or anyone

    is that possible ??

    thanks

    1 Reply Last reply
    0
    • S Offline
      S Offline
      ScottR
      wrote on last edited by
      #5

      Binary data is not "print"-able. Do a google search for "how to output binary data".

      http://www.qtforum.org/article/19923/how-to-dump-a-qbytearray-to-a-qstring-with-one-sentence.html

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #6

        Edit: only repeated the same thing as my fellows, sorry

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #7

          [quote author="freddy311082" date="1390831690"]Thank for answer JKSH and sorry for the code... I didn't know about @.[/quote]That's ok :) Thank you for editing your posts.

          [quote]I just need the binary data from file in a QString....[/quote]Why?

          If you have binary data, it's best to store it as binary data (QByteArray). It doesn't make sense to put non-strings inside QString.

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          0
          • freddy311082F Offline
            freddy311082F Offline
            freddy311082
            wrote on last edited by
            #8

            well JKSH...

            i need put the binary data in a QString because I'm trying to save a file into PostgreSQL databse.... to make that, I need to pass a query string to QSqlDatabse::exec() method and for that, I need to pass it a QString...

            let me show what I'm doing:

            @
            QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
            db.setHostName("localhost");
            db.setPort(5432);
            db.setDatabaseName("bpg");
            db.setUserName("postgres");
            db.setPassword("");
            if (db.open())
            {
            QFile file("/home/freddy/Trabajo/bpg/diseno/rubro 7.xlsx");
            if (!file.open(QIODevice::ReadOnly))
            {
            qDebug("file error...");
            exit(0);
            }

                QString bytes = file.readAll();
                file.close();
                std::cout << "sending query..." << std::endl;
                
                db.exec&#40;(QString("insert int files values (66, '{"&#41;+ bytes  +"}')"));
                db.close();
            }
            exit(EXIT_SUCCESS);
            

            @

            as you can see, into the query execution I need to pass a QString, so, I need to convert the binary file into a QString to send it to my database...

            any idea ?

            thanks anyway my friend for your answer

            freddy

            1 Reply Last reply
            0
            • JKSHJ Offline
              JKSHJ Offline
              JKSH
              Moderators
              wrote on last edited by
              #9

              I see; I misunderstood your original intent, sorry.

              You can use byteArray.toBase64() to encode your file as a binary string. toHex() works too, but produces longer strings than toBase64(). See https://qt-project.org/forums/viewthread/12281 for an example.

              By the way, for safety, it is a good idea to use SQL bindings instead of building a string directly. See:

              • http://qt-project.org/doc/qt-5/qsqlquery.html#approaches-to-binding-values
              • http://xkcd.com/327/

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply
              0
              • freddy311082F Offline
                freddy311082F Offline
                freddy311082
                wrote on last edited by
                #10

                Hi JKSH

                Thanks for your advices, they are very useful...

                Well, as I could see, I think that the problem is not with QString and QByteArray... I think that I can make a new post with my QSqlQuery question.

                the table files, which is where I'm trying to save the files, has only 2 filds. The first one is a fileid, who is an integer, and the second one is a bytea[], where I'm trying to save the binary file.

                anyway, here is my code exaple of what I'm trying to do... someone in a Postgres list told me that use a query.addBindValue, I try and nothing happend.

                here is my new code example:

                @
                QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
                db.setHostName("localhost");
                db.setPort(5432);
                db.setDatabaseName("bpg");
                db.setUserName("postgres");
                db.setPassword("");
                if (db.open())
                {
                QFile file("/home/freddy/Trabajo/bpg/diseno/rubro 7.xlsx");
                if (!file.open(QIODevice::ReadOnly))
                {
                qDebug("file error...");
                exit(0);
                }
                QByteArray bytesArr;
                QBuffer buffer(&bytesArr);
                buffer.open(QBuffer::ReadWrite);
                buffer.write(file.readAll());
                std::cout << "sending query..." << std::endl;

                    QSqlQuery query(db);
                    query.prepare("insert into files values(:id,:data)");
                    query.bindValue(":id",18);
                    query.bindValue(":data",bytesArr.toHex());
                    //query.addBindValue(bytesArr.toHex());
                    if (!query.exec&#40;&#41;)
                    {
                        qDebug(query.lastError().driverText().toLatin1());
                    }
                    cout << "query sent..." << endl;
                    file.close();
                    db.close();
                }
                

                @

                and this is the output of my program:

                @
                sending query...
                QPSQL: Unable to create query
                query sent...
                Unable to free statement: connection pointer is NULL

                *** Exited normally ***
                @

                do you remomend me that open a new post or continue here ??

                what i'm do wrong ??

                best regards

                1 Reply Last reply
                0
                • JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on last edited by
                  #11

                  You're welcome :)
                  [quote]
                  @
                  query.prepare("insert into files values(:id,:data)");
                  @
                  [/quote]Your string shouldn't have ':'

                  Check the QSqlQuery documentation again.
                  [quote]
                  @
                  QByteArray bytesArr;
                  QBuffer buffer(&bytesArr);
                  buffer.open(QBuffer::ReadWrite);
                  buffer.write(file.readAll());
                  @
                  [/quote]The buffer is unnecessary. Just read your QFile straight into your QByteArray.

                  [quote]
                  @
                  query.bindValue(":data",bytesArr.toHex());
                  @
                  [/quote]I'm not sure how the bytea type works. Maybe you can save space by using toBase64() instead of toHex(), and store your data in a string column? (I don't use PostgreSQL)

                  [quote]do you remomend me that open a new post or continue here ??[/quote]You can continue posting here, since this is your actual question. Just edit your original post to change the title.

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  1 Reply Last reply
                  0
                  • TheBadgerT Offline
                    TheBadgerT Offline
                    TheBadger
                    wrote on last edited by
                    #12

                    You can do the following to store a QByteArray directly in PostgreSQL:
                    @
                    // Create QSqlField type for your byte array
                    QSqlField byteField("Data", QVariant::ByteArray);
                    // Set the data in the QSqlField
                    byteField.setValue(bytesArr);
                    // Create the query
                    QString queryString = QString("INSERT INTO files VALUES(%1, %2);")
                    .arg(18)
                    .arg(db.driver()->formatValue(byteField));
                    // Execute the query
                    query.exec(queryString);
                    @

                    Then in PostgreSQL the column type should be BYTEA.

                    Hope this helps (its the way that I am doing it)


                    Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                    1 Reply Last reply
                    0
                    • TheBadgerT Offline
                      TheBadgerT Offline
                      TheBadger
                      wrote on last edited by
                      #13

                      To continue on my previous post:
                      To read the data again you just do:
                      @
                      // Query
                      query.exec("SELECT id, data FROM files LIMIT 1");
                      query.next();
                      QByteArray dataArray = query.value(query.record().indexOf("data")).toByteArray();
                      @

                      That should do it.


                      Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                      1 Reply Last reply
                      0
                      • freddy311082F Offline
                        freddy311082F Offline
                        freddy311082
                        wrote on last edited by
                        #14

                        Thanks for help for everybody for your help...

                        I had change the post name as JKSH recomend...

                        well Badger, your solution doesn't work my friend... I have try this:

                        @
                        QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
                        db.setHostName("localhost");
                        db.setPort(5432);
                        db.setDatabaseName("bpg");
                        db.setUserName("postgres");
                        db.setPassword("");
                        if (db.open())
                        {
                        QFile file("/home/freddy/Trabajo/bpg/diseno/rubro 7.xlsx");
                        if (!file.open(QIODevice::ReadOnly))
                        {
                        qDebug("file error...");
                        exit(0);
                        }
                        QByteArray bytesArr(file.readAll());
                        std::cout << "sending query..." << std::endl;
                        QSqlField byteField("filedata",QVariant::ByteArray);
                        QString queryStr = QString("insert into files values(%1,%2);").arg(18).arg(db.driver()->formatValue(byteField));
                        QSqlQuery query(db);
                        query.prepare(queryStr);
                        //query.addBindValue(bytesArr.toHex());
                        if (!query.exec(queryStr))
                        {
                        qDebug("query error...");
                        qDebug(query.lastError().databaseText().toLatin1());
                        }
                        cout << "query sent..." << endl;
                        file.close();
                        db.close();
                        }
                        @
                        and the output is this:
                        @
                        Starting: /home/freddy/Trabajo/bpg/kdevelop/bpg/build/bpg
                        sending query...
                        query error...
                        ERROR: array value must start with "{" or dimension information
                        LINE 1: insert into files values(18,'\x504b030414000600080000002100e...
                        ^
                        (22P02)
                        query sent...
                        *** Exited normally ***
                        @

                        I try to add a '{' to the begining of the QArrayBuffer, after append the bytesArray reading from the file, and finaly, y append to the end of the end of the array the '}' character and ther error is the same.

                        Postgres require that the data for the insert query for the bytea field must be between characters {} or with le length information at the beginin...

                        i think that the proble is exactly how put the binary field between {}... i havd try with this and the result is the same:
                        @
                        QByteArray bytesArr;
                        bytesArr.append('{');
                        bytesArr.append(file.readAll());
                        bytesArr.append('}')
                        @

                        best regards...

                        1 Reply Last reply
                        0
                        • TheBadgerT Offline
                          TheBadgerT Offline
                          TheBadger
                          wrote on last edited by
                          #15

                          That is very interesting... I cant see a difference between your code and my code (except for the application specific stuff).

                          What version of Qt are you using and PostgreSQL?
                          Mine is: Qt 4.8.1
                          PostgreSQL: 9.1

                          I am still looking into the problem, hopefully I can post an update that might help.

                          Sorry for that


                          Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                          1 Reply Last reply
                          0
                          • freddy311082F Offline
                            freddy311082F Offline
                            freddy311082
                            wrote on last edited by
                            #16

                            That's Ok Badger...

                            I'm using Qt5.2, Postgres 9.3 and Archlinux.

                            I have try with the post which told me JKSH but the problem still remain. The problem is how I can put the binary data between {} for postgres query....

                            1 Reply Last reply
                            0
                            • TheBadgerT Offline
                              TheBadgerT Offline
                              TheBadger
                              wrote on last edited by
                              #17

                              Quick though, try:
                              @
                              QString queryStr = QString("insert into files values(%1,'%2');").arg(18).arg(db.driver()->formatValue(byteField));
                              @
                              or
                              @
                              QString queryStr = QString("insert into files values(%1,'{%2}');").arg(18).arg(db.driver()->formatValue(byteField));
                              @

                              or something based on the second without the quotes.


                              Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                              1 Reply Last reply
                              0
                              • freddy311082F Offline
                                freddy311082F Offline
                                freddy311082
                                wrote on last edited by
                                #18

                                with the first code the output is this:
                                @
                                Starting: /home/freddy/Trabajo/bpg/kdevelop/bpg/build/bpg
                                sending query...
                                query error...
                                ERROR: syntax error at or near ""
                                LINE 1: insert into files values(18,''\x504b030414000600080000002100...
                                ^
                                (42601)
                                query sent...
                                *** Exited normally ***
                                @
                                and with the second is this one:
                                @
                                Starting: /home/freddy/Trabajo/bpg/kdevelop/bpg/build/bpg
                                sending query...
                                query error...
                                ERROR: syntax error at or near ""
                                LINE 1: insert into files values(18,'{'\x504b03041400060008000000210...
                                ^
                                (42601)
                                query sent...
                                *** Exited normally ***
                                @

                                1 Reply Last reply
                                0
                                • TheBadgerT Offline
                                  TheBadgerT Offline
                                  TheBadger
                                  wrote on last edited by
                                  #19

                                  My best guess is it is then something with the versions. An example in my PostgreSQL log of a successful query is:
                                  @
                                  SELECT SCHEMA.update_element(1, 9, '2014-1-29 16:55:03.411', '\xaaaaaaaa00000000000000000000000
                                  @

                                  (only the first part is shown, but that is out of the log, with some name updates )

                                  [edit: clicked post instead of preview]


                                  Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                                  1 Reply Last reply
                                  0
                                  • TheBadgerT Offline
                                    TheBadgerT Offline
                                    TheBadger
                                    wrote on last edited by
                                    #20

                                    The difference is that I am using a stored procedure in postgreSQL to update the table, the stored procedure is defined as:
                                    @
                                    CREATE OR REPLACE FUNCTION SCHEMA.update_element(
                                    nr_1 INTEGER,
                                    nr_2 INTEGER,
                                    time_arg TIMESTAMP WITH TIME ZONE,
                                    data_arg BYTEA
                                    )
                                    RETURNS VOID AS
                                    $$
                                    DECLARE
                                    BEGIN
                                    -- input into table with update
                                    END;
                                    $$
                                    @

                                    But from my limited understanding is that that should be basically the same in handling the BYTEA field.


                                    Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                                    1 Reply Last reply
                                    0
                                    • freddy311082F Offline
                                      freddy311082F Offline
                                      freddy311082
                                      wrote on last edited by
                                      #21

                                      yes brother... I will see in a Postgres forum

                                      thanks anyway

                                      1 Reply Last reply
                                      0
                                      • TheBadgerT Offline
                                        TheBadgerT Offline
                                        TheBadger
                                        wrote on last edited by
                                        #22

                                        My conclusion is PostgreSQL version change that made this happen (I might be wrong).

                                        My code:
                                        @
                                        QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
                                        /* Set the default values for the database connection */
                                        db.setHostName("127.0.0.1");
                                        db.setPort(5432);
                                        db.setDatabaseName("my_db");
                                        db.setUserName("postgres");
                                        db.setPassword("postgres");

                                        if (db.open())
                                        {
                                            QByteArray bytesArr("Some test byte array");
                                            qDebug() << "sending query...";
                                            QSqlField byteField("filedata", QVariant::ByteArray);
                                            byteField.setValue(bytesArr); // need this
                                            QString queryStr = QString("INSERT INTO files VALUES(%1,%2);")
                                                               .arg(18)
                                                               .arg(db.driver()->formatValue(byteField));
                                            QSqlQuery query(db);
                                            query.prepare(queryStr);
                                        
                                            qDebug() << "Query: " << queryStr;
                                            //query.addBindValue(bytesArr.toHex());
                                            if (!query.exec&#40;queryStr&#41;&#41;
                                            {
                                                qDebug("query error...");
                                                qDebug(query.lastError().databaseText().toLatin1());
                                            } else {
                                                qDebug() << "query sent...";
                                            }
                                            db.close();
                                        }
                                        

                                        @

                                        My output:
                                        @
                                        sending query...
                                        Query: "INSERT INTO files VALUES(18,'\x536f6d6520746573742062797465206172726179');"
                                        query sent...
                                        @

                                        The result, an updated column in my database.

                                        Somewhere I think there is a version incompatibility. Perhaps one can make a bug request on some place, not sure where the solution should be.

                                        Good luck, these types of problems are very annoying.

                                        [edit: took out IP and db name]


                                        Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                                        1 Reply Last reply
                                        0
                                        • TheBadgerT Offline
                                          TheBadgerT Offline
                                          TheBadger
                                          wrote on last edited by
                                          #23

                                          Me again :P

                                          Try something like this, to check the PostgreSQL server:
                                          @
                                          QString hackedString;
                                          hackedString = db.driver()->formatValue(byteField);
                                          hackedString.insert(1, '{');
                                          hackedString.insert(hackedString.length() - 1, '}');
                                          qDebug() << "hacked string: " << hackedString;
                                          QString queryStr = QString("INSERT INTO files VALUES(%1,%2);")
                                          .arg(18)
                                          .arg(hackedString);
                                          @

                                          *just replace the relevant code in your code.

                                          The string looks fine according to what the error says, but my server responds with "ERROR: invalid input syntax for type bytea".


                                          Check out my SpellChecker Plugin for Qt Creator @ https://github.com/CJCombrink/SpellChecker-Plugin

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved