Bild in bytea über MS Access

Alle Fragen und Probleme zu den externen Schnittstellen wie ODBC, JDBC, ...
melodoi
Neuer Benutzer
Beiträge: 22
Registriert: Mo 5. Jan 2009, 18:05

Bild in bytea über MS Access

Beitrag von melodoi » Mo 5. Jan 2009, 19:02

Hi,

ich habe mein MS Access 2000 Frontend MySQL au PostGreSQL umgestellt. Bis auf ein Problem mit den ehemaligen blob-Daten geht auch alles. Für die bilter nutze ich nun bytea und geife folgendermaßend lesend und schreibend mittels ADO 2.7 über PG-ODBC Vers.8.03.04.00 (UNICODE) drauf zu:

schreiben:

Code: Alles auswählen

Public Function InsertPixFile(strQuelle As String, strPixFile, ID As Variant)
On Error GoTo Err_InsertPixFile
'Diese Prozedur speichert eine Datei (strPixFile) unter dem Namen in strName in
'der Tabelle Bilder binär im Feld "Bild"

    Dim pix() As Byte
    Dim rs As ADODB.Recordset
    Dim strSQL As String
    Dim F As Integer
    F = FreeFile
   
    If Nz(ID) = "" Then Exit Function
   
    Open strPixFile For Binary As #F
        ReDim pix(LOF(F))
        Get #F, , pix()
    Close #F
   
    Select Case strQuelle
    Case "Paket"
        strSQL = "SELECT Bild AS Pic, BildName AS PicName FROM tbl_P_Paket " _
            & "WHERE Deleted=0 AND ID_Paket=" & ID
    Case "Sparepart"
        strSQL = "SELECT picture AS Pic, picturename AS PicName FROM spareparts_details " _
            & "WHERE id_spareparts_details=" & ID
    Case "NIK_Anlagen"
        strSQL = "SELECT document AS Pic, document_name AS PicName FROM tbl_kunden_documents " _
            & "WHERE id_kunden_documents=" & ID
    Case "Spareparts_Dokument"
        strSQL = "SELECT document AS Pic, document_name AS PicName FROM spareparts_documents " _
            & "WHERE id_spareparts_documents=" & ID
    Case "Pakete_Dokument"
        strSQL = "SELECT document AS Pic, document_name AS PicName FROM tbl_p_documents " _
            & "WHERE id_p_documents=" & ID
    End Select
    Set rs = New ADODB.Recordset
    Set rs = clsODBC.GetSQL(strSQL)
    With rs
        If .RecordCount = 0 Then
            MsgBox "Bitte speichern Sie Ihre Eingaben bevor Sie ein Bild/Datei hinzufügen.", _
                vbOKOnly + vbInformation, "Speichern"
        Else
            'Binär speichern
            rs("Pic").AppendChunk pix()
            rs("PicName") = Mid(strPixFile, InStrRev(strPixFile, "") + 1)
            .Update
        End If
        .Close
        Set rs = Nothing
    End With
   
Exit_InsertPixFile:
    Erase pix
    Set rs = Nothing
    Exit Function
Err_InsertPixFile:
    Reset
    FehlerAufnahme strModul, "InsertPixFile"
    Resume Exit_InsertPixFile
End Function


lesen:

Code: Alles auswählen

Public Function CreatePix(strQuelle As String, ByRef strPicName As String, ID As Long) As StdPicture
On Error GoTo Err_CreatePix

    Dim rs As ADODB.Recordset
    Dim pix() As Byte
    Dim lSize As Long
    Dim strSQL As String
    Dim Resultat As Double
    Dim F As Integer
    F = FreeFile

    If ID = 0 Then Exit Function

    Select Case strQuelle
    Case "Paket"
        strSQL = "SELECT Bild AS Pic, BildName AS PicName FROM tbl_P_Paket WHERE Deleted=0 AND ID_Paket=" & ID
    Case "Sparepart"
        strSQL = "SELECT picture AS Pic, picturename AS PicName FROM spareparts_details " _
            & "WHERE id_spareparts_details=" & ID
    Case "Tyres"
        strSQL = "SELECT picture AS Pic, picturename AS PicName FROM spareparts_details " _
            & "WHERE id_spareparts_details=" & ID
    Case "Anlagen_Kunden"
        strSQL = "SELECT document AS Pic, document_name AS PicName FROM tbl_kunden_documents " _
            & "WHERE id_kunden_documents=" & ID
    Case "Anlagen_Pakete"
        strSQL = "SELECT document AS Pic, document_name AS PicName FROM tbl_p_documents " _
            & "WHERE id_p_documents=" & ID
    Case "Anlagen_Spareparts"
        strSQL = "SELECT document AS Pic, document_name AS PicName FROM spareparts_documents " _
            & "WHERE id_spareparts_documents=" & ID
    End Select
    Set rs = New ADODB.Recordset
    Set rs = clsODBC.GetSQL(strSQL)
    With rs
        If .RecordCount > 0 Then
            lSize = rs("Pic").ActualSize
            If Not lSize = 0 Then
                ReDim pix(lSize)
                pix() = rs("Pic").GetChunk(lSize)       'Binärdaten in Arry laden
                Set CreatePix = BytesToPicture(pix)     'Siehe Funktion im Modul mdlArrayToStdPicture
                strPicName = rs("PicName")
                'Das passiert bei nicht unterstützten Bildformaten
                If CreatePix Is Nothing Then MsgBox "Das Bildformat wird nicht unterstützt oder die " _
                    & "Anlage ist nicht vorhanden oder defekt. Laden Sie die Anlage neu!", _
                    vbOKOnly + vbCritical, "Anlage kann nicht angezeigt werden"
            End If
        Else
            Erase pix
        End If
        .Close
        Set rs = Nothing
    End With
   
    If Left(strQuelle, 8) = "Anlagen_" Then
        Open GetSpecFolder(CSIDL_PERSONAL) & "\Anlagen_" & strPicName For Binary As #F
            Put #F, , pix
        Close #F
        MsgBox "Die Anlage wurde unter '" & GetSpecFolder(CSIDL_PERSONAL) & "\Anlagen_" & strPicName _
            & "' abgelegt. Es wird nun versucht diese Anlage zur Anzeige zu bringen. Sollte dies " _
            & "nicht gelingen, verfügen Sie über keinen geeignetten Viewer für dieses Dateiformat.", _
            vbOKOnly + vbInformation, "Anlage anzeigen"
        Resultat = ShellExecute(0, "open", GetSpecFolder(CSIDL_PERSONAL) & "\Anlagen_" & strPicName, "", "", vbNormalFocus)
    End If
   
Exit_CreatePix:
    Erase pix
    Set rs = Nothing
    Exit Function
Err_CreatePix:
    FehlerAufnahme strModul, "CreatePix"
    Resume Exit_CreatePix
End Function


die Datenbankabfrage geschieht so:

Code: Alles auswählen

Public Function GetSQL(ByVal strSQL As String) As ADODB.Recordset
On Error GoTo Err_GetSQL
'Ausführen SQL-Abfrage

    Set GetSQL = New ADODB.Recordset
    GetSQL.CursorLocation = adUseClient
    GetSQL.Open strSQL, CurrentProject.Connection, adOpenKeyset, adLockOptimistic   'adOpenDynamic, adLockOptimistic
   
Exit_Err_GetSQL:
    Exit Function
Err_GetSQL:
        MsgBox "Fehler Nummer " & Err.Number & " (" & Err.description & ") in 'GetSQL' aufgetreten"
    Resume Exit_Err_GetSQL
End Function


Bei .AppendChunk und .GetChunk erhalte ich jeweis den Fehler "3219 Der Vorgang ist in diesem Zusammenhang nicht zugelassen."
Komisch ist auch dass bei lSize = rs("Pic").ActualSize immer 255 raus kommt, was nicht sein kann. Hat jemand eine Idee dazu?

Danke Sylvio

akretschmer
Erfahrener Benutzer
Beiträge: 7684
Registriert: So 29. Okt 2006, 13:35
Wohnort: Kaufbach, Sachsen, Germany, Germany
Kontaktdaten:

Beitrag von akretschmer » Mo 5. Jan 2009, 19:56

melodoi hat geschrieben:Hi,

ich habe mein MS Access 2000 Frontend MySQL au PostGreSQL umgestellt. Bis auf ein Problem mit den ehemaligen blob-Daten geht auch alles.


Die Fehlermeldungen kommen nicht von PG, sondern von M$-Dingens.

Ich kann Dir nur empfehlen, in PG zu loggen, und zwar sowohl die ankommenden Befehle als auch die evtl. Fehler.

Andreas
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

melodoi
Neuer Benutzer
Beiträge: 22
Registriert: Mo 5. Jan 2009, 18:05

In PostGre loggen

Beitrag von melodoi » Mo 5. Jan 2009, 21:08

Hi Andreas,

danke für den Tip. Probiere ich morgen gleich! Da ich Neuling bei PG bin, kann du mir bitte noch sagen wo oder wie ich das Loggig aktiviere und wo das Log-File oder so dann liegt?

LG Sylvio

ads
Erfahrener Benutzer
Beiträge: 4148
Registriert: Mi 8. Feb 2006, 10:58
Wohnort: MD
Kontaktdaten:

Beitrag von ads » Mo 5. Jan 2009, 21:48

In der Datei postgresql.conf wird alles definiert, was du benötigst. Dort stehen auch die Pfade zur Logdatei.

Näheres vermittelt dir die Dokumentation, in diese solltest du wirklich den ein oder anderen Blick werfen ;-)
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören Bild

Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler

PostgreSQL Service & Support

melodoi
Neuer Benutzer
Beiträge: 22
Registriert: Mo 5. Jan 2009, 18:05

Feedback folgt...

Beitrag von melodoi » Mo 5. Jan 2009, 22:06

OK, danke!!! Ich geb hier Feedback, wenn ich das Problem lösen konnte.

ads
Erfahrener Benutzer
Beiträge: 4148
Registriert: Mi 8. Feb 2006, 10:58
Wohnort: MD
Kontaktdaten:

Beitrag von ads » Mo 5. Jan 2009, 22:33

melodoi hat geschrieben:Ich geb hier Feedback, wenn ich das Problem lösen konnte.

Das ist nett, Danke schön.
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören Bild

Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler

PostgreSQL Service & Support

melodoi
Neuer Benutzer
Beiträge: 22
Registriert: Mo 5. Jan 2009, 18:05

Log-File

Beitrag von melodoi » Di 6. Jan 2009, 11:07

Hi Andreas,

also du hattest recht mit der Vermutung, dass es nicht an PG liegt. Ich habe alle Logs aktiviert und folgende Einträge erhalten:

2009-01-06 08:00:27 STATEMENT: SELECT "picture" ,"picturename" FROM "public"."spareparts_details" WHERE ("id_spareparts_details" = 448187 )

2009-01-06 08:00:27 DEBUG: StartTransaction

2009-01-06 08:00:27 STATEMENT: SELECT "picture" ,"picturename" FROM "public"."spareparts_details" WHERE ("id_spareparts_details" = 448187 )

2009-01-06 08:00:27 DEBUG: name: unnamed; blockState: DEFAULT; state: INPROGR, xid/subid/cid: 12837418/1/0, nestlvl: 1, children: <>

2009-01-06 08:00:27 STATEMENT: SELECT "picture" ,"picturename" FROM "public"."spareparts_details" WHERE ("id_spareparts_details" = 448187 )

2009-01-06 08:00:27 DEBUG: CommitTransactionCommand

2009-01-06 08:00:27 STATEMENT: SELECT "picture" ,"picturename" FROM "public"."spareparts_details" WHERE ("id_spareparts_details" = 448187 )

2009-01-06 08:00:27 DEBUG: CommitTransaction

2009-01-06 08:00:27 STATEMENT: SELECT "picture" ,"picturename" FROM "public"."spareparts_details" WHERE ("id_spareparts_details" = 448187 )

2009-01-06 08:00:27 DEBUG: name: unnamed; blockState: STARTED; state: INPROGR, xid/subid/cid: 12837418/1/0, nestlvl: 1, children: <>

2009-01-06 08:00:27 STATEMENT: SELECT "picture" ,"picturename" FROM "public"."spareparts_details" WHERE ("id_spareparts_details" = 448187 )

2009-01-06 08:00:28 DEBUG: StartTransactionCommand


Wo könnte das Problem nun liegen? ODBC? Access? Datentyp in PG?

melodoi
Neuer Benutzer
Beiträge: 22
Registriert: Mo 5. Jan 2009, 18:05

Aufgabe anders gelöst

Beitrag von melodoi » Di 6. Jan 2009, 17:03

Es schein mit diesem ODBC-Treiber garnicht zu gehen.

Ich hab nun ein etwas "speziellen" Weg eingeschlagen :) . Ich kodiere die binäre Datei mit Base64 und lege sie als Text in die Datenbank. Sie wird zwar 1/3 größer aber ich bin unabhängig vom Datenbanktyp binary (longblob, bytea,...). Rückwärtz wird der Text wieder dekodiert und in ein Array umgewandelt, das dann direkt zur Anzeige oder in eine Datei gespeichert werden kann. Das ganze geht so ähnlich wie bei Email-Anlagen.

Gruß Sylvio

akretschmer
Erfahrener Benutzer
Beiträge: 7684
Registriert: So 29. Okt 2006, 13:35
Wohnort: Kaufbach, Sachsen, Germany, Germany
Kontaktdaten:

Beitrag von akretschmer » Di 6. Jan 2009, 17:40

melodoi hat geschrieben:Es schein mit diesem ODBC-Treiber garnicht zu gehen.

Ich hab nun ein etwas "speziellen" Weg eingeschlagen :) . Ich kodiere die binäre Datei mit Base64 und lege sie als Text in die Datenbank.


Das ist übrigens mit BYTEA auch nötig (base64 oder escaped oder hex).
Vielleicht war nur das Dein Fehler...

Andreas
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

ads
Erfahrener Benutzer
Beiträge: 4148
Registriert: Mi 8. Feb 2006, 10:58
Wohnort: MD
Kontaktdaten:

Beitrag von ads » Di 6. Jan 2009, 23:52

Bytea sollte man auch ohne Umwege ansprechen können, nur braucht man dafür andere Funktionen. Die "regulären" Funktionen - in C geschrieben - können keine binären Daten verarbeiten. Da ist beim ersten Null-Byte Schluß.
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören Bild

Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler

PostgreSQL Service & Support

Antworten