Search code examples
pythonsqlitejpegpygtkgtk3

how to store a jpg in an sqlite database with python


I've been trying for many days to find a solution to this problem. I need to write a small jpg image for each record in an sqlite database. Finally I managed to insert the file but judging from the size it was written in the database as raw instead of a (compressed) jpg. The code I used is:

imgobj = Image.open('./fotocopies/checks/633.jpg')
con = sqlite3.connect("pybook.db")
cur = con.cursor()
cur.execute("UPDATE data_fotocopies SET fotocopy=? WHERE refid=633 and reftype=0", [ buffer(imgobj.tobytes()) ] )

If I try to open the file it cannot be inserted in the database so, the following code:

imgobj = open('./fotocopies/checks/632.jpg')
con = sqlite3.connect("pybook.db")
cur = con.cursor()
cur.execute("UPDATE data_fotocopies SET fotocopy=? WHERE refid=632 and reftype=0", [sqlite3.Binary(imgobj)] )

gives the following error:

cur.execute("UPDATE data_fotocopies SET fotocopy=? WHERE refid=632 and reftype=0", [sqlite3.Binary(imgobj)] )
TypeError: buffer object expected

Unfortunately no previous answer in stackoverflow covers me as I've tried them all. Furthermore all the storing retrieving has to be done via a gtk3 interface which I suspect will mean another (series of) problem(s) i.e. how to set an existing image to get its data from the db response etc. Can anyone help?


Solution

  • Finally I got it working thanks to Andrej Kesely's comment. The working solution is

    imgobj = base64.b64encode(open('./fotocopies/checks/624.jpg').read())
    con = sqlite3.connect("pybook.db")
    cur = con.cursor()
    qf="UPDATE data_fotocopies SET fotocopy='%s' WHERE refid=%d AND reftype=0"%(lite.Binary(fotocopy_blob),id)
    cur.execute(qf) #yes, it is dangerous for injection`
    

    and retrieving the image from the database is done as:

    qf="SELECT fotocopy FROM data_fotocopies WHERE refid=%d and reftype=0"%self.check_id
    self.cur.execute(qf)
    try:
        fd=base64.b64decode(self.cur.fetchall()[0][0])
        byting = GLib.Bytes(fd)
        self.fotocopy = Gio.MemoryInputStream.new_from_bytes(byting)
        ...
    self.fotocopy_ent=self.builder.get_object("fotocopy")         # as it is made in glade
    pixbuf = GdkPixbuf.Pixbuf.new_from_stream(self.fotocopy,None) #finally the pixbuf although 
                                                                  #it produces errors if I have
                                                                  #no stream/image to "feed" it.
    self.fotocopy_ent.set_from_pixbuf(pixbuf)
    

    Still can't figure out why all other solutions I've found don't work. I use Python 2.7.6 ang gtk3, but this one I subit does.

    Thank you all for your help.