在 PostgreSQL 中,
bytea_output
参数控制在查询结果中
bytea
类型的显示格式。默认情况下,
bytea_output
的值为
hex
,这意味着在查询结果中,
bytea
类型的数据以十六进制格式显示。但是,如果你的应用程序期望以二进制格式获取图像数据,则将
bytea_output
设置为
escape
可能更适合。无论
bytea_output
参数设置为
hex
还是
escape
,你都可以通过 C# 访问 PostgreSQL 数据库,并且正常获取并显示图片。本篇随笔介绍这个问题的处理过程。

1、碰到的数据库图片在界面显示问题

在我们的Winform框架中,由于底层是支持多种数据库的设计,因此可以兼容MS SQLServer、Oracle、Mysql、PostgreSQL、SQLite等数据库的,但是一般我们用的是SQLServer、MySql居多,有客户切换到PostgreSQL数据库的时候,发现图片显示不正常,需要对图片进行十六进制转换才能正常显示。

默认的方式,这里方框在SQLServer等数据库上是正常显示图标的,打开编辑也是可以展示菜单的图表的,不过由于切换到PostgreSQL后,这里图标消失,检查数据库操作,默认的处理都是一致的,因此考虑是否为数据库参数配置问题。

2、解决问题

打开ChatGPT,或者百度、Google一下,细心都可以发现,在 PostgreSQL 中默认情况下,
bytea_output
的值为
hex
,这意味着在查询结果中,
bytea
类型的数据以十六进制格式显示。如果你的应用程序期望以二进制格式获取图像数据,则将
bytea_output
设置为
escape
可能更适合。

我们找到PostgreSQL的安装目录,找到 C:\Program Files\PostgreSQL\13\data\postgresql.conf里面的数据库配置文件,找到
bytea_output
的值查看。

果然发现其默认值为hex,我们按要求修改为 escape,并去掉注释符号#,如下所示。

重启PostgreSQL,并测试系统数据库,显示和保存处理正常。

3、两种方式处理的差异

如果
bytea_output
参数设置为
hex
,你可以通过将读取到的十六进制字符串转换为字节数组,然后使用这些字节数组来创建图像对象。以下是一个示例代码,演示了如何在 C# 中获取并显示图片,即使
bytea_output
参数设置为
hex

classProgram
{
static voidMain()
{
string connString = "Host=myServerAddress;Port=myPort;Username=myUsername;Password=myPassword;Database=myDatabase";using (var conn = newNpgsqlConnection(connString))
{
conn.Open();
//执行 SQL 查询以获取图像数据 string sql = "SELECT image_column FROM your_table WHERE id = @id";int id = 1; //替换为你要查询的图像的 ID using (var cmd = newNpgsqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue(
"@id", id);//读取图像数据 using (var reader =cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if(reader.Read())
{
//获取十六进制字符串 string hexString = reader.GetString(0);//将十六进制字符串转换为字节数组 byte[] imageData =StringToByteArray(hexString);//创建图像对象 using (MemoryStream ms = newMemoryStream(imageData))
{
Image image
=Image.FromStream(ms);//显示图像 ShowImage(image);
}
}
}
}
}
}
static voidShowImage(Image image)
{
//创建一个新的窗体 using (var form = newSystem.Windows.Forms.Form())
{
//创建 PictureBox 控件 var pictureBox = newSystem.Windows.Forms.PictureBox();
pictureBox.Dock
=System.Windows.Forms.DockStyle.Fill;
pictureBox.Image
=image;//将 PictureBox 添加到窗体中 form.Controls.Add(pictureBox);//设置窗体大小并显示 form.Size = newSystem.Drawing.Size(image.Width, image.Height);
form.ShowDialog();
}
}
static byte[] StringToByteArray(stringhex)
{
int NumberChars = hex.Length / 2;byte[] bytes = new byte[NumberChars];using (var sr = newStringReader(hex))
{
for (int i = 0; i < NumberChars; i++)
bytes[i]
= Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
}
returnbytes;
}
}

如果
bytea_output
参数设置为
escape
,则可以直接使用 Npgsql 从数据库中读取图像数据,并将其转换为字节数组,而不需要进行额外的处理。以下是示例代码:

usingNpgsql;usingSystem;usingSystem.Data;usingSystem.Drawing;usingSystem.IO;classProgram
{
static voidMain()
{
string connString = "Host=myServerAddress;Port=myPort;Username=myUsername;Password=myPassword;Database=myDatabase";using (var conn = newNpgsqlConnection(connString))
{
conn.Open();
//执行 SQL 查询以获取图像数据 string sql = "SELECT image_column FROM your_table WHERE id = @id";int id = 1; //替换为你要查询的图像的 ID using (var cmd = newNpgsqlCommand(sql, conn))
{
cmd.Parameters.AddWithValue(
"@id", id);//读取图像数据 using (var reader =cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if(reader.Read())
{
//获取图像数据字节数组 byte[] imageData = (byte[])reader["image_column"];//创建图像对象 using (MemoryStream ms = newMemoryStream(imageData))
{
Image image
=Image.FromStream(ms);//显示图像 ShowImage(image);
}
}
}
}
}
}
static voidShowImage(Image image)
{
//创建一个新的窗体 using (var form = newSystem.Windows.Forms.Form())
{
//创建 PictureBox 控件 var pictureBox = newSystem.Windows.Forms.PictureBox();
pictureBox.Dock
=System.Windows.Forms.DockStyle.Fill;
pictureBox.Image
=image;//将 PictureBox 添加到窗体中 form.Controls.Add(pictureBox);//设置窗体大小并显示 form.Size = newSystem.Drawing.Size(image.Width, image.Height);
form.ShowDialog();
}
}
}

无论
bytea_output
参数设置为
hex
还是
escape
,你都可以通过 C# 访问 PostgreSQL 数据库,并且正常获取并显示图片。

标签: none

添加新评论