在PostgreSQL数据库中插入图像

17
我想知道如何将“bytea”格式的图片插入到我的PostgreSQL数据库表中。我已经在论坛上搜索了几个小时,看到了同样的问题被发布了数十次,但是还没有找到一个答案。我只看到如何将.jpeg文件插入到旧列中,这不是我所需要的。 这是数据库表格:
create table category  (
"id_category" SERIAL,
"category_name" TEXT,
"category_image" bytea,
constraint id_cat_pkey primary key ("id_category"))without oids;

当我添加新行时,它不能正常工作:

insert into category(category_name,category_image) values('tablette', lo_import('D:\image.jpg'));

使用编程语言提取文件内容,或者如果您无法这样做并且您是超级用户并且该文件位于服务器上,请参阅dba.se上的“如何将(文件)数据插入PostgreSQL bytea列”(http://dba.stackexchange.com/questions/1742)。 - Daniel Vérité
1
通常最好的做法是将图像保存为磁盘上的文件,然后只在数据库中存储对它的引用。 - Björn Nilsson
1
你使用的是哪种编程语言和客户端驱动程序?此外,“lo_import”不适用于“bytea”字段,而是适用于大型对象(“lob”,“pg_largeobject”),根据文档说明。 - Craig Ringer
我使用工具pgAdmin III来创建和填充我的postgreSql数据库。 - Sarra
我想知道对于bytea类型,lo_import的等效函数是什么。 - Sarra
显示剩余3条评论
8个回答

7
如果列类型为 bytea,则可以简单地使用 'pg_read_binary_file'。
例如:pg_read_binary_file('/path-to-image/') 请查阅postgresql文档中的pg_read_binary_file

4

以上所有示例都不适用于我,而且我需要一次添加多个图像。

完整的工作示例(使用Python 3),并附有解释:

使用get_binary_array获取图像(或文件)的值作为二进制数组,将其路径和文件名作为参数传递(例如:'/home/Pictures/blue.png')。

使用send_files_to_postgresql一次性发送所有图像。

我之前创建了一个具有自动增量的顺序'id'和一个bytea 'image'字段的数据库(但您也可以使用自己的手工制作id)。

import psycopg2

def get_binary_array(path):
    with open(path, "rb") as image:
        f = image.read()
        b = bytes(f).hex()
        return b

def send_files_to_postgresql(connection, cursor, file_names):
    query = "INSERT INTO table(image) VALUES (decode(%s, 'hex'))"
    mylist = []
    for file_name in file_names:
        mylist.append(get_binary_array(file_name))

    try:
        cursor.executemany(query, mylist)
       
        connection.commit()  # commit the changes to the database is advised for big files, see documentation
        count = cursor.rowcount # check that the images were all successfully added
        print (count, "Records inserted successfully into table")
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)

def get_connection_cursor_tuple():
    connection = None
    try:
        params = config()
        print('Connecting to the PostgreSQL database...')
        connection = psycopg2.connect(**params)
        cursor = connection.cursor()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)

    return connection, cursor

connection, cursor = connect_db.get_connection_cursor_tuple()
img_names = ['./blue.png', './landscape.jpg']
send_files_to_postgresql(connection, cursor, img_names)

3
insert into category(category_name,category_image) values('tablette', bytea('D:\image.jpg'));

上面的解决方案适用于列类型为bytea。
insert into category(category_name,category_image) values('tablette', lo_import('D:\image.jpg'));

上述解决方案适用于列类型为oid,即Blob的情况。
insert into category(category_name,category_image) values('tablette',decode('HexStringOfImage',hex));

上述解码函数有两个参数。第一个参数是图像的十六进制字符串。第二个参数默认为十六进制。解码函数将十六进制字符串转换为字节并存储在Postgres中的bytea数据类型列中。


28
bytea('D:\image.jpg')并不会从指定的文件中读取图像,它只是将字符串常量'D:\image.jpg'转换为其二进制表示形式。请注意不要改变原文的意思。 - user330315
插入到类别表中(category) (category_name, category_image) 的值为('tablette', 'R0lGODlhmgDAAIcAAAgICAGAAY8ZGQAAgIqCFYKEhxRGEkVKF73D')。 - Ravi
将给定的图像转换为base64编码字符串并粘贴到那里。我只是上面给出了一个简单的例子。但是,如果列数据类型为oid,则对我有效。 - Ravi
有没有办法通过给定路径而不是 'D:\image.jpg' 作为二进制文件来插入文件? - vizsatiz
插入到类别表中(category) (category_name, category_image) 的值为('tablette', lo_import('D:\image.jpg'))。 - Ravi
1
我们还可以使用insert into category(category_name,category_image) values('tablette',decode('base 64 image string','base64')); - Navap

0
对于Linux用户,这是如何添加图像路径的。
insert into blog(img) values(bytea('/home/samkb420/Pictures/Sam Pics/sam.png'));

0
create table images (imgname text, img bytea);


insert into images(imgname,img) values ('MANGO', pg_read_binary_file('path_of_image')::bytea);

4
您的答案可以通过添加更多支持性信息来改进。请[编辑]以添加进一步的细节,例如引用或文档,以便他人可以确认您的答案是否正确。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

0

类似这个函数(稍作修改自此处)可能会起作用。

create or replace function img_import(filename text)
  returns void
  volatile
  as $$
    declare
        content_ bytea;
        loid oid;
        lfd integer;
        lsize integer;
    begin
        loid := lo_import(filename);
        lfd := lo_open(loid,131072);
        lsize := lo_lseek(lfd,0,2);
        perform lo_lseek(lfd,0,0);
        content_ := loread(lfd,lsize);
        perform lo_close(lfd);
        perform lo_unlink(loid);

    insert into category values
    ('tablette',
    content_);
    end;
$$ language plpgsql

使用方法如下:select * from img_import('D:\image.jpg'); 或者如果感觉需要的话,可以重写为存储过程。


0
创建如下函数:
create or replace function bytea_import(p_path text, p_result out bytea) 
                       language plpgsql as $$
    declare
      l_oid oid;
    begin
      select lo_import(p_path) into l_oid;
      select lo_get(l_oid) INTO p_result;
      perform lo_unlink(l_oid);
    end;$$;

并像这样使用:

insert into table values(bytea_import('C:\1.png'));

-4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接