【问题标题】:Storing Zip file in Postgres在 Postgres 中存储 Zip 文件
【发布时间】:2014-09-27 09:52:32
【问题描述】:

我一直将 zip 文件的内容存储在 MySQL 数据库中的 LONGBLOB 中,但我正在转向 Postgres。根据我的阅读,Postgres 中的 LONGBLOB 是 bytea。不幸的是,我无法将 zip 内容写入数据库。首先,我得到了这个错误:

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

然后我用 SQL_ASCII 编码创建了一个新的数据库(以前是 UTF8),得到了这个错误:

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;Ω░#╩...

有什么方法可以在 Postgres 中创建数据库/表/列而不进行编码?如果没有,我应该如何存储这些信息?我尝试使用 pg_escape_bytea 但是当我尝试解压缩内容时会产生错误。不确定这真的很重要,但这是我用来写入数据库的 PHP:

$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));
}

【问题讨论】:

  • 你不能使用绑定参数让PostgreSQL驱动处理正确编码二进制数据吗?
  • 永远,永远,永远使用addslashes。如果你正在使用它,那是一个巨大的闪烁警告,上面写着“这里可能存在安全漏洞”。在这种情况下,您应该清楚地使用参数化查询。

标签: php mysql sql postgresql encoding


【解决方案1】:

bytea 输入格式之一是十六进制。所以使用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

顺便说一句,如果你不知道,你很容易受到 SQL 注入的影响。

【讨论】:

  • 这对我有用,从数据库中读取时我只需要使用$content = substr($content, 2);$content = hex2bin($content);
【解决方案2】:

现在是切换到 PDO 的好机会,它可以干净利落地完成这类事情。

Here's an earlier answer I wrote on this topic,其中讨论了旧式 PostgreSQL 驱动程序对二进制数据真正糟糕的多种方式。

简短的版本是您的代码应该更像:

$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();

【讨论】:

  • 感谢您的回答!绝对有帮助,尽管我最终使用了 Clodoaldo 的方法。
【解决方案3】:

尝试使用base64encode()函数:

$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));
}

当您需要这些数据时,请使用 base64decode() 函数。此外,您的列类型必须是文本才能存储此数据。

字符串 base64_encode (字符串 $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

【讨论】:

  • 使用这种方法我没有看到写入数据库的任何错误,但是当我尝试从数据库中读取时,zip 文件仍然损坏(我没有忘记使用 base64_decode)。如果有帮助,我可以发布我用来从数据库中读取的 php 代码。
  • 我写了一个简单的脚本在我的本地机器上测试它,没关系。粘贴您的代码,将检查它
  • 您可能需要更改数据库排序规则
猜你喜欢
  • 2020-11-18
  • 1970-01-01
  • 2012-10-18
  • 2020-02-14
  • 2012-03-11
  • 2011-05-02
  • 2021-01-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多