bilder in eine mysql datenbank speichern
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Stimmt - man kann auch einfach das Schreibrecht nur für den User des Serverprozesses geben und damit ist das gelöst.jens hat geschrieben:Einfach ist es allerdings ein Verz. zu erstellen, das Schreibrechte für alle zu geben und dann dorthin die Daten zu speichern. Ich mag es alledings nicht so gern, ein Verz. mit Schreibrechte für alle
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Genau.Leonidas hat geschrieben:Stimmt - man kann auch einfach das Schreibrecht nur für den User des Serverprozesses geben und damit ist das gelöst.
Allerdings laufen CGI Skripte im SharedWebhosting i.d.R. als User nobody Group nobody... Man muß also ein wenig aufpassen
Hi ihr beiden!
Also ich bekomme es nicht hin
Langsam komme ich mir so vor, als wenn ich mich zu dumm anstelle...
Also ich habe mal ein Beispiel gemacht, in dem ich es so versuche, wie jens es mir geschildert hat.
Interessant sind Zeilen 60-67
Wenn ihr wxPython nicht installiert habt, könnt ihr anhand der Methode LoadPic sehen, was ich da tue.
Es klappt so nicht. Ich bekomme einen Fehler von MySQL zurück.
Kurze Erklärung, warum ich Bilder in der DB speichern will.
Für unseren Flugverein entwickle ich an einem Programm. Jeder bekommt einen Client, DB-Server ist im Netz. Im Personenverzeichnis will ich jedem Mitglied anbieten, ein kleines Bild von sich hochzuladen. Damit die anderen es auch gleich zu Hause sehen können, muss es in der DB liegen.
Viele Grüße
Jamil
Also ich bekomme es nicht hin
Langsam komme ich mir so vor, als wenn ich mich zu dumm anstelle...
Also ich habe mal ein Beispiel gemacht, in dem ich es so versuche, wie jens es mir geschildert hat.
Interessant sind Zeilen 60-67
Code: Alles auswählen
# -*- coding: iso-8859-1 -*-
# File: test.py
import wx
import MySQLdb
import base64
HOST = 'localhost'
PORT = 3306
USER = 'FPK'
PASSW = 'kmmanager'
DB = 'afv'
"""
CREATE TABLE test (
`test_id` int(10) unsigned NOT NULL auto_increment,
`test_blob` blob,
PRIMARY KEY (`test_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
"""
#------------------------------------------------------------------------
class MyFrame(wx.Dialog):
def __init__(self, parent, title):
wx.Dialog.__init__(self, parent, -1, title,
pos=(150, 150), size=(300, 350))
self.ConnectToDB()
panel = wx.Panel(self, -1)
self.emptyBmp = wx.EmptyBitmap(width=400, height=400)
self.pic = wx.StaticBitmap(panel, -1, self.emptyBmp)
self.btn_Load = wx.Button(panel, -1, 'Lade und speichere Bild')
self.btn_Load.Bind(wx.EVT_BUTTON, self.LoadPic)
self.btn_Remove = wx.Button(panel, -1, 'Entferne Bild')
self.btn_Remove.Bind(wx.EVT_BUTTON, self.RemovePic)
self.btn_Remove.Disable()
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
btn_sizer.Add(self.btn_Load, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
btn_sizer.Add(self.btn_Remove, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(self.pic, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
main_sizer.Add(btn_sizer, 0, wx.ALL|wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
panel.SetSizer(main_sizer)
main_sizer.Fit(self)
self.main_sizer = main_sizer
self.Bind(wx.EVT_CLOSE, self.OnClose)
#------------------------------------------------------------------------
def LoadPic(self, event):
wildcard = "Alle Bilddateien|*.bmp;*.jpg;*.png;*.jpeg;*.gif"
dlg = wx.FileDialog(
self, message='Wähle eine Bilddatei', defaultDir=wx.StandardPaths.Get().GetUserConfigDir(),
defaultFile="", wildcard=wildcard, style=wx.OPEN | wx.FILE_MUST_EXIST
)
if dlg.ShowModal() == wx.ID_OK:
file_path = dlg.GetPaths()[0]
image = wx.Image(file_path, wx.BITMAP_TYPE_ANY)
self.SetPictureImage(image)
f = file(file_path, 'r')
data = f.read()
data = base64.encodestring(data)
self.SQL('INSERT INTO test SET test_blob=' + data + ';')
f.close()
self.btn_Remove.Enable()
if event:
event.Skip()
#-------------------------------------------------
def SetPictureImage(self, image):
w, h = float(image.GetWidth()), float(image.GetHeight())
targetSize = 400.0
if h != targetSize:
scale = h / targetSize
image = image.Scale(w / scale, h / scale)
bmp = wx.BitmapFromImage(image)
self.pic.SetSize((bmp.GetWidth(), bmp.GetHeight()))
self.pic.SetBitmap(bmp)
self.main_sizer.Layout()
#------------------------------------------------------------------------
def RemovePic(self, event):
self.pic.SetBitmap(self.emptyBmp)
self.btn_Remove.Disable()
#------------------------------------------------------------------------
def ConnectToDB(self):
self.Con = MySQLdb.Connect(host = HOST,
port = PORT,
user = USER,
passwd = PASSW,
db = DB)
#------------------------------------------------------------------------
def SQL(self, statement):
Cursor = self.Con.cursor()
Cursor.execute(statement)
result = Cursor.fetchall()
self.Con.commit()
return result
#------------------------------------------------------------------------
def OnClose(self, event):
self.Con.close()
self.Destroy()
#------------------------------------------------------------------------
class MyApp(wx.App):
def OnInit(self):
dialog = MyFrame(None, 'Bild in Blob speichern')
if dialog.ShowModal() == wx.ID_OK:
print dialog.object.GetDate()
return True
app = MyApp(0)
app.MainLoop()
Es klappt so nicht. Ich bekomme einen Fehler von MySQL zurück.
Code: Alles auswählen
_mysql_exceptions.ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/9j/4AAQSkZJRgABAgEASABIAAD/4Q8cRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAE=' at line 1")
Für unseren Flugverein entwickle ich an einem Programm. Jeder bekommt einen Client, DB-Server ist im Netz. Im Personenverzeichnis will ich jedem Mitglied anbieten, ein kleines Bild von sich hochzuladen. Damit die anderen es auch gleich zu Hause sehen können, muss es in der DB liegen.
Viele Grüße
Jamil
Zuletzt geändert von JR am Mittwoch 22. November 2006, 21:28, insgesamt 1-mal geändert.
Hi JR,
ich bin mir nicht sicher, aber überlass das Einfügen des Wertes mal dem SQL Modul.
So sollte es funktionieren:
Gruß, Whitie
ich bin mir nicht sicher, aber überlass das Einfügen des Wertes mal dem SQL Modul.
So sollte es funktionieren:
Code: Alles auswählen
...
f = file(file_path, 'r')
data = f.read()
f.close()
data = base64.encodestring(data)
self.SQL('INSERT INTO test SET test_blob=%s', (data,))
...
def SQL(self, statement, vals):
Cursor = self.Con.cursor()
if vals:
# Wenn Werte in vals sind
Cursor.execute(statement, vals)
else:
# Wenn leerer Tupel übergeben wurde
Cursor.execute(statement)
result = Cursor.fetchall()
Con.commit()
return result
Hi Whitie!
Habe das probiert, MySQl liefert zwar keinen Fehler mehr, doch wenn ich mir den Spaltenwert über dem MySQL-Query Browser ansehe, erkennt er nicht, dass es ein Bild ist. Das geht sonst immer. Er speichert irgendwas ab, aber es ist zerhauen.
Blöd, dass es so schwierig ist
Jamil
Habe das probiert, MySQl liefert zwar keinen Fehler mehr, doch wenn ich mir den Spaltenwert über dem MySQL-Query Browser ansehe, erkennt er nicht, dass es ein Bild ist. Das geht sonst immer. Er speichert irgendwas ab, aber es ist zerhauen.
Blöd, dass es so schwierig ist
Jamil
Kann man Blobs überhaupt mit normalen literalen SQL-Inserts einfügen? Das sind doch Binärdaten, da dürfte doch alles möglich vorkommen was ausserhalb von ASCII-Text liegt. Ich würde das auch dem DB-Modul überlassen.
Hi rayo und BlckJack!
Zunächst zum Modus, wie ich die Datei lese. In meinem Python-GEPACKT Buch zu Python 2.4 wurde dieser Modus gar nicht erwähnt. Was für eine Enttäuschung.
So hat es geklappt.
Das Bild ist in der DB gelandet.
Schwere Geburt. Vielen vielen Dank für eure Hilfe.
Hier ist der funktionierende Code:
Viele Grüße
Jamil
Zunächst zum Modus, wie ich die Datei lese. In meinem Python-GEPACKT Buch zu Python 2.4 wurde dieser Modus gar nicht erwähnt. Was für eine Enttäuschung.
So hat es geklappt.
Das Bild ist in der DB gelandet.
Schwere Geburt. Vielen vielen Dank für eure Hilfe.
Hier ist der funktionierende Code:
Code: Alles auswählen
# -*- coding: iso-8859-1 -*-
# File: test.py
import wx
import MySQLdb
import base64
HOST = 'localhost'
PORT = 3306
USER = 'FPK'
PASSW = 'kmmanager'
DB = 'afv'
"""
CREATE TABLE test (
`test_id` int(10) unsigned NOT NULL auto_increment,
`test_blob` blob,
PRIMARY KEY (`test_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
"""
#------------------------------------------------------------------------
class MyFrame(wx.Dialog):
def __init__(self, parent, title):
wx.Dialog.__init__(self, parent, -1, title,
pos=(150, 150), size=(300, 350))
self.ConnectToDB()
panel = wx.Panel(self, -1)
self.emptyBmp = wx.EmptyBitmap(width=400, height=400)
self.pic = wx.StaticBitmap(panel, -1, self.emptyBmp)
self.btn_Load = wx.Button(panel, -1, 'Lade und speichere Bild')
self.btn_Load.Bind(wx.EVT_BUTTON, self.LoadPic)
self.btn_Remove = wx.Button(panel, -1, 'Entferne Bild')
self.btn_Remove.Bind(wx.EVT_BUTTON, self.RemovePic)
self.btn_Remove.Disable()
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
btn_sizer.Add(self.btn_Load, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
btn_sizer.Add(self.btn_Remove, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
main_sizer = wx.BoxSizer(wx.VERTICAL)
main_sizer.Add(self.pic, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
main_sizer.Add(btn_sizer, 0, wx.ALL|wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 15)
panel.SetSizer(main_sizer)
main_sizer.Fit(self)
self.main_sizer = main_sizer
self.Bind(wx.EVT_CLOSE, self.OnClose)
#------------------------------------------------------------------------
def LoadPic(self, event):
wildcard = "Alle Bilddateien|*.bmp;*.jpg;*.png;*.jpeg;*.gif"
dlg = wx.FileDialog(
self, message='Wähle eine Bilddatei', defaultDir=wx.StandardPaths.Get().GetUserConfigDir(),
defaultFile="", wildcard=wildcard, style=wx.OPEN | wx.FILE_MUST_EXIST
)
if dlg.ShowModal() == wx.ID_OK:
file_path = dlg.GetPaths()[0]
image = wx.Image(file_path, wx.BITMAP_TYPE_ANY)
self.SetPictureImage(image)
f = file(file_path, 'rb')
data = f.read()
# data = base64.encodestring(data)
f.close()
self.SQL('INSERT INTO test SET test_blob=%s', [data,])
f.close()
self.btn_Remove.Enable()
if event:
event.Skip()
#-------------------------------------------------
def SetPictureImage(self, image):
w, h = float(image.GetWidth()), float(image.GetHeight())
targetSize = 400.0
if h != targetSize:
scale = h / targetSize
image = image.Scale(w / scale, h / scale)
bmp = wx.BitmapFromImage(image)
self.pic.SetSize((bmp.GetWidth(), bmp.GetHeight()))
self.pic.SetBitmap(bmp)
self.main_sizer.Layout()
#------------------------------------------------------------------------
def RemovePic(self, event):
self.pic.SetBitmap(self.emptyBmp)
self.btn_Remove.Disable()
#------------------------------------------------------------------------
def ConnectToDB(self):
self.Con = MySQLdb.Connect(host = HOST,
port = PORT,
user = USER,
passwd = PASSW,
db = DB)
#------------------------------------------------------------------------
def SQL(self, statement, parameters=None):
Cursor = self.Con.cursor()
Cursor.execute(statement, parameters)
result = Cursor.fetchall()
self.Con.commit()
return result
#------------------------------------------------------------------------
def OnClose(self, event):
self.Con.close()
self.Destroy()
#------------------------------------------------------------------------
class MyApp(wx.App):
def OnInit(self):
dialog = MyFrame(None, 'Bild in Blob speichern')
if dialog.ShowModal() == wx.ID_OK:
print dialog.object.GetDate()
return True
app = MyApp(0)
app.MainLoop()
Jamil
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Wie, dann geht das bei dir jetzt ohne base64??? Bei mir funktioniert das einfach nicht... Wobei mein insert Befehl ist auch leicht anders:
'INSERT INTO test SET test_blob=%s'
"INSERT INTO TabellenName (data) VALUES (%s);"
Übrigends machst du zweimal ein f.close() (Zeile 69). Außerdem erwartet die execute Methode ein tuple und keine Liste. Also statt [data,] sollte es (data,) sein
'INSERT INTO test SET test_blob=%s'
"INSERT INTO TabellenName (data) VALUES (%s);"
Übrigends machst du zweimal ein f.close() (Zeile 69). Außerdem erwartet die execute Methode ein tuple und keine Liste. Also statt [data,] sollte es (data,) sein
Hi Jens!
Also dass man auch eine Liste anstelle eines Tupels an execute weitergeben darf, habe ich getestet. Ist auch wesentlich angenehmer, dass ich viele Statements im Code dynamisch zusammensetze. Dies geht mit einem Tupel nicht.
Zweimal f.close() ist ein Versehen.
Das Einfügen eines Bildes habe ich so gemacht.
Code nur als Prinzipdarstellung:
Grüße und danke für die vielen Tipps
Jamil
Also dass man auch eine Liste anstelle eines Tupels an execute weitergeben darf, habe ich getestet. Ist auch wesentlich angenehmer, dass ich viele Statements im Code dynamisch zusammensetze. Dies geht mit einem Tupel nicht.
Zweimal f.close() ist ein Versehen.
Das Einfügen eines Bildes habe ich so gemacht.
Code nur als Prinzipdarstellung:
Code: Alles auswählen
f = file('C:\\Bild.jpg', 'rb')
blobdata = f.read()
f.close()
cursor.execute('INSERT INTO <table> SET test_blob=%s;', [blobdata,])
Jamil
Ich hab das ja schon oft gesehen und oft nachgefragt und ich will hier auch kein Fass aufmachen, aber ich hab es einfach noch nie verstanden: warum speichert man Bilder in einer SQL-Datenbank? Das bläht das ganze doch nur unnötig auf. Ich speichere in der Datenbank lediglich den Speicherort des Bildes samt Namen. Das kann ich dann schön in einer Query mit abfragen (z.B. zeig mir alle JPEGs oder alle im Ordner 'Britney'). Die Binärdaten des Bildes bringen mir doch i.d.R. gar nichts, außer wenn ich die Dateigröße abfragen will. Ich glaube, das Dateisystem, das im Prinzip ja auch eine Datenbank darstellt, ist für Binärdaten viel besser optimiert was die Performance anbelangt als jede SQL-Datenbank.
Es gibt für alles eine rationale Erklärung.
Außerdem gibt es eine irrationale.
Wie man Fragen richtig stellt
Außerdem gibt es eine irrationale.
Wie man Fragen richtig stellt
Sorry, hatte ich zuerst nicht gesehen. Die Serveranwendung besteht also lediglich aus der DB. Alles andere ist clientseitig implementiert. Richtig?JR hat geschrieben:Weshalb ich das mache, habe ich oben beschrieben.
Es gibt für alles eine rationale Erklärung.
Außerdem gibt es eine irrationale.
Wie man Fragen richtig stellt
Außerdem gibt es eine irrationale.
Wie man Fragen richtig stellt
Hi!
Ja, so ist es. Jedes Vereinsmitglied bekommt den Client zum Installieren. Die Daten liegen auf einem MySQL-Server. Sie werden zum einen in unserem Internetportal (Plone) angezeigt, können aber komfortabler über die Clientsoftware verwaltet werden.
Daten bestehen aus Personenverzeichnis, Flugerfassungen, Benutzerverwaltung etc.
Gruß
Jamil
Ja, so ist es. Jedes Vereinsmitglied bekommt den Client zum Installieren. Die Daten liegen auf einem MySQL-Server. Sie werden zum einen in unserem Internetportal (Plone) angezeigt, können aber komfortabler über die Clientsoftware verwaltet werden.
Daten bestehen aus Personenverzeichnis, Flugerfassungen, Benutzerverwaltung etc.
Gruß
Jamil
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Und ich mache es wegen dem nobody Problem, siehe: http://www.python-forum.de/post-49934.h ... body#49934
@JR: Was ich dir noch sagen wollte: Nach dem du ein Bild gelöscht hast, mußt du immer ein "OPTIMIZE TABLE" machen, damit der Speicherplatz auch frei wird.
Das mache ich bei mir in def delete():
http://pylucid.net/trac/browser/PyLucid ... ge.py#L592
@JR: Was ich dir noch sagen wollte: Nach dem du ein Bild gelöscht hast, mußt du immer ein "OPTIMIZE TABLE" machen, damit der Speicherplatz auch frei wird.
Das mache ich bei mir in def delete():
http://pylucid.net/trac/browser/PyLucid ... ge.py#L592