0

I've been storing the contents of zip files in a LONGBLOB in a MySQL database, but I'm moving to Postgres. From what I've read, the equivalent to LONGBLOB in Postgres is bytea. Unfortunately, I can't get the zip contents to write to the database. First, I got this error:

Warning: pg_query(): Query failed: ERROR:  invalid byte sequence for encoding "UTF8"
 0x5c

Then I created a new database with SQL_ASCII encoding (the previous had UTF8), and got this error:

PHP Warning:  pg_query(): Query failed: ERROR:  syntax error at or near "v╘▓ú5"
LINE 2: ...√╢V[úB√▬┌»å⌐²└ù╙±b±≡ß▼┐π}°ï»┌G╜₧╧εo»~°0o╞W/_╝ƒL¢\'v╘▓ú5;Ω░#╩...

Is there any way to create a database/table/column in Postgres without encoding? If not, how should I store this information? I tried using pg_escape_bytea but that produces errors when I try to unzip the contents. Not sure that this really matters, but here's the PHP I'm using to write to the database:

$content = file_get_contents($zipLocation);
$content = addslashes($content);

$sql="INSERT INTO ZIP_TBL ( BUILD, CONTENT)
    VALUES ('$build', '$content')";

if (!pg_query($con,$sql)) {
    die('Error: ' . pg_last_error($con));
}
Michael A
  • 89
  • 1
  • 9
  • Can't you use a bound parameter and let the PostgreSQL driver deal with properly encoding the binary data? – mu is too short Aug 04 '14 at 20:59
  • Never, ever, ever use `addslashes`. If you're using it, that's a giant flashing warning saying "probable security bug here". In this case you should *clearly* be using a parameterzed query. – Craig Ringer Aug 05 '14 at 01:09

3 Answers3

3

One of the bytea input formats is hexadecimal. So use bin2hex

$content = file_get_contents($zipLocation);
$content = '\\x' . bin2hex($content);

$sql="
    insert into zip_tbl ( build, content)
    values ('$build', E'$content')
";

http://www.postgresql.org/docs/current/static/datatype-binary.html#AEN5318

http://php.net/manual/en/function.bin2hex.php

BTW, if you are not aware, you are susceptible to SQL injection.

Clodoaldo Neto
  • 118,695
  • 26
  • 233
  • 260
  • This worked for me, I just had to use `$content = substr($content, 2);` and `$content = hex2bin($content);` when reading it from the database – Michael A Aug 05 '14 at 14:47
2

Now is a good opportunity to switch to PDO, which does this sort of thing cleanly and sanely.

Here's an earlier answer I wrote on this topic, which discusses the numerous ways in which the old-style PostgreSQL driver is truly awful for binary data.

The short version is that your code should be more like:

$sth = $pdo->prepare('INSERT INTO mytable(somecol, byteacol) VALUES (:somecol, :byteacol)');
$sth->bindParam(':somecol', 'bork bork bork');
$sth->bindParam(':byteacol', $thebytes, PDO::PARAM_LOB);
$sth->execute();
Community
  • 1
  • 1
Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
0

Try to use base64encode() function:

$content = file_get_contents($zipLocation);
$content = base64encode($content);

$sql="INSERT INTO ZIP_TBL ( BUILD, CONTENT)
    VALUES ('$build', '$content')";

if (!pg_query($con,$sql)) {
    die('Error: ' . pg_last_error($con));
}

And when you will need this data back, use base64decode() function. Also, type of your column needs to be text to store this data.

string base64_encode ( string $data )

string base64_decode ( string $data [, bool $strict = false ] )

http://php.net//manual/en/function.base64-decode.php

http://php.net//manual/en/function.base64-encode.php

fiction
  • 566
  • 1
  • 6
  • 21
  • Using this method I don't see any errors writing to the database, but when I try to read from the database the zip file is still corrupted ( I didn't forget to use base64_decode). I could post the php code I'm using to read from the database if that would help. – Michael A Aug 04 '14 at 20:32
  • i wrote simple script to test it at my local machine and it's all right. Paste your code, will check it – fiction Aug 04 '14 at 20:38
  • You might need to change database collation – user1587985 Aug 04 '14 at 20:38