[SOLVED]How send binary file to Postgres server?
-
Hello friends
I have this code:
@
QFile file("/home/freddy/Trabajo/bpg/diseno/rubro 7.xlsx");
if (!file.open(QIODevice::ReadOnly))
{
file.close();
exit(0);
}QByteArray bytes = file.readAll(); file.close(); QString allBytes; for(int i = 0; i < bytes.length(); i++) allBytes+= bytes.at(i); qDebug(todosLosBytes.toLatin1()); exit(0);
@
I'm trying to print in console the content of the file because I need the content of the file in a QString variable and it doesn't work.if I write inside the ciclo std::cout << bytes.at(i), the content of the file is printing in console, but when I add it to my QString variable it doesn't work.
I can changethe ciclo and put only allBytes = bytes I have the same problem...
what I'm suppose to to to fix my problem?? what i'm doing wrong ??
best regards
Freddy
[edit, code tags, koahnig]
-
sorry.... the code was not pasted well...
here is my code again
@
QFile file("/home/freddy/Trabajo/bpg/diseno/rubro 7.xlsx");
if (!file.open(QIODevice::ReadOnly))
{
std::cout <<"error" << std::endl;
exit(0);
}QByteArray bytes = file.readAll();
file.close();
QString allBytes;
for(int i = 0; i < bytes.length(); i++)
allBytes+= bytes.at(i);
qDebug(allBytes.toLatin1());
@best regards
[code tags added, koahnig]
-
Hi,
.xlsx is a compressed file format. You can't convert it directly to a string because its data is not plain text. (If you try to open the .xlsx file with a text editor, you will see garbage values).
If you create a .txt file and write some text inside, you can convert the bytes directly to a string.
By the way, add '@' before and after your code to make it easier to read. If you make a mistake, you can click "edit" on the right -- you don't need to post twice.
-
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
-
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
-
Edit: only repeated the same thing as my fellows, sorry
-
[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.
-
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((QString("insert int files values (66, '{")+ 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
-
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:
-
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()) { 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
-
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.
-
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)
-
-
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...
-
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.1I am still looking into the problem, hopefully I can post an update that might help.
Sorry for that
-
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....
-
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.
-
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 ***
@ -
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]
-
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.