在PostgreSQL中存储类似BLOB的数据

时间:2012-06-22 19:14:36

标签: php postgresql

我最近从MySQL切换到PostgreSQL。我有一个问题。

以前,我会在MySQL中以BLOB格式存储小图像。

PostgreSQL不知道BLOB这样的东西。

我尝试使用BYTEA字段类型。这实际上插入一个大的(十六进制?)字符串我猜,但现在我不知道试图让这个字符串回到在PHP中显示实际图像..

有什么想法吗?提前谢谢。

以下是我用于将图像保存在数据库中的一段代码:

$data = bin2hex(file_get_contents('php://input'));

if (!empty($data)) {
  $sql = "UPDATE asset SET data = X'%s' WHERE uuid = '%s'";
  $args = array($data, $asset_uuid);
}
使用

psql(9.1.3)和php 5.3.6

3 个答案:

答案 0 :(得分:3)

Bytea是一个字节数组。这不是一点点模式。请参阅PostgreSQL Lexical Structure的第4.2.1.5节。

输入bytea的正确方法是带有十六进制值的'\ x ...'。所以你想要的是SET data ='\ x%s'。

您可能还想查看使用pg_prepare的预准备语句。

编辑:我能够将(文本)文件插入到bytea中:

$source = file_get_contents( 'hello.php' );
$insert = pg_prepare( $conn, '', 'insert into t (name, data) values($1,$2)' );
pg_execute( $conn, '', array( 'hello.php', $source ) );

3rd Edit:将文件插入数据库时​​可以正常工作。但是,PHP中的pgsql驱动程序非常不礼貌。检索实际数据的唯一方法是使用 bytea转义机制,详见此处:pg_unescape_bytea

pg_query('SET bytea_output = "escape";');

$result = pg_query( 'select data from t' );

while ( $row = pg_fetch_row( $result ) ) {
    echo pg_unescape_bytea( $row[0] );
}

我很抱歉这有多烦人。 PHP中的PostgreSQL接口可以对二进制值进行一些重大改进。

答案 1 :(得分:3)

使用pg_ * API插入bytea内容,二进制值应始终通过pg_escape_bytea()函数运行,即使它已传递给pg_execute或{{ 1}}功能。 这是因为pg_ *层不“知道”特定参数具有二进制内容,并且它无论如何都不实现对参数类型的任何实际支持。因此必须使用文本表示。它可以是pg_query_params形式,也可以是escape形式,它与PG服务器无关,它与hex的值无关,仅对值有意义从服务器读取。

示例:

bytea_output

要使用pg_ * API 读取bytea内容,必须在获取后通过$esc=pg_escape_bytea("\000\001\002"); pg_query_params('INSERT INTO some_table(some_col) VALUES($1)', array($esc)); 运行该值。假设客户端库不是9.0(libq.so.5.3或更高版本),它可以解码内容,无论是pg_unescape_bytea()形式还是hex形式,它都会自动检测它。只有使用较旧的库,才有必要强制escape bytea_output才能正确解码,可以使用escape动态解码,也可以静态解码整个数据库(SET)或在整个实例的ALTER DATABASE SET bytea_output=escape中。

示例:

postgresql.conf

答案 2 :(得分:2)

这里发布的两个答案给了我一些想法,但没有一个是100%的答案。

所以,我将在这个答案中解释我为了让它发挥作用所做的一切。

显示图像时,我使用了这个:

header('Content-Type: image/jpeg');

$data = pack("H*", pg_unescape_bytea($data));

echo $data;

我正在运行PHP 5.3.8,在PHP 5.4.0中,事实证明你可以使用hex2bin而不是pack。

将图像添加到数据库时,我使用了这个:

$data = pg_escape_bytea($data); // Escape input for PostgreSQL
$sql  = "UPDATE asset SET data = '%s'WHERE uuid = '%s'";

我很高兴它现在正在运作。谢谢丹尼尔和约翰!