17

I would like to know How can I insert an image "bytea" into a table of my postgreSql database? I've been searching forums for hours and have seen the same question posted dozens of times, but yet to find a single answer. All I see is how to insert .jpeg's into an old column which isn't what I need.

Here's the database table:

create table category  (
"id_category" SERIAL,
"category_name" TEXT,
"category_image" bytea,
constraint id_cat_pkey primary key ("id_category"))without oids;

and when I add a new line, it doesn't work :

insert into category(category_name,category_image) values('tablette', lo_import('D:\image.jpg'));
Wissem SASSI
  • 2,181
  • 2
  • 9
  • 13
Sarra
  • 353
  • 2
  • 3
  • 12
  • Use a programming language to extract the file contents, or if you can't and you're superuser and the file is on the server, see [How to insert (file) data into a PostgreSQL bytea column](http://dba.stackexchange.com/questions/1742) on dba.se – Daniel Vérité Mar 09 '14 at 23:24
  • 1
    It is usually a better idea to save the image as a file on disk and just store a reference to it in the database. – Björn Nilsson Mar 09 '14 at 23:56
  • 1
    Which programming language and client driver are you using? Also, `lo_import` isn't for `bytea` fields, it's for large objects (`lob`, `pg_largeobject`), per the documentation. – Craig Ringer Mar 10 '14 at 00:06
  • @Björn Nilsson: how can i save the image as o file on disk and how can i store the reference in my database? – Sarra Mar 10 '14 at 08:20
  • I used the tool pgAdmin III to create and populate my postgreSql database – Sarra Mar 10 '14 at 08:23
  • I want to know what is the equivalent function of lo_import for bytea type – Sarra Mar 10 '14 at 08:48
  • The equivalent is `pg_read_binary_file(filename text [, offset bigint, length bigint])` in the [System Administration Functions](http://www.postgresql.org/docs/current/static/functions-admin.html) – Daniel Vérité Mar 10 '14 at 13:31
  • I put this in PgAdminIII: insert into category (category_name,category_image) values('tablette',pg_read_binary_file('D:\tablette.jpg')); and an error appears: ERREUR: chemin absolu non autorisé ********** Erreur ********** ERREUR: chemin absolu non autorisé État SQL :42501 – Sarra Mar 10 '14 at 14:48

8 Answers8

7

If the column type is bytea then you can simply use the 'pg_read_binary_file'.

Example: pg_read_binary_file('/path-to-image/')

check postgresql documentation of pg_read_binary_file

Mowazzem Hosen
  • 457
  • 4
  • 10
4

None of the above example worked well for me and on top of that I needed to add many images at once.

Full working example (python 3) with explanations:

With get_binary_array we get the value of the image (or file) as a binary array, using its path and file name as parameter (ex: '/home/Pictures/blue.png').

With send_files_to_postgresql we send all the images at once.

I previously created the database with one sequential 'id' that will automatically be incremented (but you can use your own homemade id) and one bytea 'image' field

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)
smartse
  • 1,026
  • 7
  • 12
Antonin GAVREL
  • 9,682
  • 8
  • 54
  • 81
3
insert into category(category_name,category_image) values('tablette', bytea('D:\image.jpg'));

The above solution works if column type is bytea

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

The above solution works if column type is oid i.e., Blob

insert into category(category_name,category_image) values('tablette',decode('HexStringOfImage',hex));

The above decode function take two parameters. First parameter is HexString of Image.The second parameter is hex by default.Decode function coverts the hexString to bytes and store in bytea datatype column in postgres.

Ravi
  • 159
  • 3
  • 17
  • 28
    `bytea('D:\image.jpg')` will **not** read the image from the file specified. It simply converts the string constant `'D:\image.jpg'` to its binary representation. –  Sep 20 '17 at 06:22
  • insert into category(category_name,category_image) values('tablette', 'R0lGODlhmgDAAIcAAAgICAGAAY8ZGQAAgIqCFYKEhxRGEkVKF73D'); – Ravi Sep 20 '17 at 09:18
  • Convert the given image to base64 encode string and paste there. I just given an simple example above. However it worked for me if column data type is oid. – Ravi Sep 20 '17 at 09:19
  • Is there a way I can insert a file by giving the path and not `'D:\image.jpg'` as binary ? – vizsatiz Nov 03 '18 at 06:23
  • insert into category(category_name,category_image) values('tablette', lo_import('D:\image.jpg')); – Ravi Nov 03 '18 at 09:22
  • 1
    We can also use `insert into category(category_name,category_image) values('tablette',decode('base 64 image string','base64'));` – Navap May 29 '20 at 02:03
0

Something like this function (slightly adapted from here) could work out.

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

Use it like select * from img_import('D:\image.jpg'); or rewrite to procedure if feeling like it.

Community
  • 1
  • 1
im_infamous
  • 972
  • 1
  • 17
  • 29
0

create below function:

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

and use like this:

insert into table values(bytea_import('C:\1.png'));
Govind Gupta
  • 1,555
  • 4
  • 15
  • 24
0

For Linux users this is how to add the path to the image

insert into blog(img) values(bytea('/home/samkb420/Pictures/Sam Pics/sam.png'));
samkb420
  • 26
  • 4
0
create table images (imgname text, img bytea);


insert into images(imgname,img) values ('MANGO', pg_read_binary_file('path_of_image')::bytea);
SHARKOP
  • 1
  • 1
  • 4
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 05 '21 at 12:26
-4

Use SQL workbench - Database explorer - insert a row and follow the dialogue...

enter image description here