我最近从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
答案 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'";
我很高兴它现在正在运作。谢谢丹尼尔和约翰!