Campi BLOB MySql e file Pdf

di il
6 risposte

Campi BLOB MySql e file Pdf

In un applicazione Access interfacciata con MySql sto lavorando sulla gestione di file PDF inseriti in campi BLOB. Premetto che ho posizionato le tabelle deputate in un database separato per evitare problemi di backup e restore con campi BLOB sul database principale. Queste tabelle sono di tipo MyIsam. In ogni caso non è questo il problema. Il problema è che al momento non trovo il modo di ricreare il file PDF originale quando ne ho bisogno. Posso leggerlo attraverso un recordset ADO, poi? Penso di dover usare i file binari sui quali non ho esperienza. Se qualcuno può già indirizzarmi con qualche frammento di codice sarei ben contento.  

Riporto il codice di un test non andato a buon fine. La sub WriteBinaryStringToFile l'ho trovata in rete. Nel chiamante ci sono delle routine mie, l'importante è che in strTemp mi ritrovo il mio campo BLOB dove ho salvato il PDF che voglio ricreare.

Il file viene creato ma non è riconosciuto da Adobe.

Sub WriteBlob()
 Dim rst As ADODB.Recordset, strTemp As String
 strTemp = "SELECT PdfBlob FROM tila_20241108_PDF.tblInvPb_Pdf"
 Set rst = rstSqlRead(strTemp)
 strTemp = rst!PdfBlob & ""
 ObjClose rst
 WriteBinaryStringToFile "E:\Scr\Test.Pdf", strTemp
End Sub

Sub WriteBinaryStringToFile(strFile As String, hex_val As String)
   Dim handle As Long
   handle = FreeFile
   Open strFile For Binary As #handle
   Seek #handle, LOF(handle) + 1
   Put #handle, , hex_val
   Close #handle
End Sub

Edit: Seconda versione con l'uso di una variabile Byte e strConv, stesso risultato

Sub WriteBlob()
 Dim rst As ADODB.Recordset, strTemp As String, x() As Byte
 strTemp = "SELECT PdfBlob FROM tila_20241108_PDF.tblInvPb_Pdf"
 Set rst = rstSqlRead(strTemp)
 strTemp = rst!PdfBlob & ""
 ObjClose rst
 x = StrConv(strTemp, vbFromUnicode)
 WriteBinaryStringToFile "E:\Scr\Test1.Pdf", x
End Sub
Sub WriteBinaryStringToFile(strFile As String, hex_val)
   Dim handle As Long
   handle = FreeFile
   Open strFile For Binary As #handle
   Seek #handle, LOF(handle) + 1
   Put #handle, , hex_val
   Close #handle
End Sub

6 Risposte

  • Re: Campi BLOB MySql e file Pdf

    Trovato, era semplicissimo, si fa attraverso MySql stesso

    SELECT PdfBlob INTO DUMPFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/test.pdf' FROM tila_20241108_pdf.tblinvpb_pdf;
  • Re: Campi BLOB MySql e file Pdf

    19/11/2024 - Catafirro ha scritto:


    Dim strTemp As String

    Qui trovi il probabile colpevole : potrebbe essere un problema di lunghezza insufficiente della stringa.

    I blob in genere si manipolano utilizzano i metodi GetChunk e AppendChunk (applicabili a DAO e ADO) che ti permetto di suddividere un campo binario in porzioni della lunghezza che preferisci.

    Questo è come salvo su file di testo un campo Blob, come vedi limito a 31999 bytes la lunghezza della singola scrittura (ho un vago ricordo di un lunghezza massima delle stringhe di 32767 bytes ) :

    
    Public Function ManageMemoField(DaoRs As DAO.Recordset, sField As String, sDestination As String, bWriteToFile As Boolean) As Boolean
    Dim iFreeFile       As Integer
    Dim i               As Integer
    
    Dim RetVal          As Variant
    Dim iBlockSize      As Integer
    Dim lFileLength     As Long
    Dim lLeftOver       As Long
    Dim lStartByte      As Long
    Dim iNumBlocks      As Integer
    Dim sFileData       As String
    Dim bTooLong        As Boolean
    
    '
    ' sDestination parameter can be :
    ' File to write OLE field (bWriteToFile = true)
    ' String To be filled with OLE Field content (bWriteToFile = False)
    '
    
    On Error GoTo Lbl_Err
    iBlockSize = 512
    bTooLong = False
    
    ' Get the size of the field.
    lFileLength = DaoRs(sField).FieldSize()
    If lFileLength = 0 Then
        ManageMemoField = False
        Exit Function
    End If
    
    ' Calculate number of blocks to write and leftover bytes.
    iNumBlocks = lFileLength \ iBlockSize
    lLeftOver = lFileLength Mod iBlockSize
    
    If bWriteToFile Then
        ' Open the destination file.
        iFreeFile = FreeFile()
        Open sDestination For Binary As #iFreeFile
    Else
        sDestination = ""
    End If
    ' Write the leftover data to the output file.
    lStartByte = 0
    sFileData = DaoRs(sField).GetChunk(lStartByte, lLeftOver)
    If bWriteToFile Then
        Put #iFreeFile, , sFileData
    Else
        If Len(sFileData) < 32000 Then
            sDestination = sFileData
        Else
            bTooLong = True
        End If
    End If
    ' Write the remaining blocks of data to the output file.
    For i = 1 To iNumBlocks
        ' Reads a chunk and writes it to output file.
        lStartByte = (i - 1) * iBlockSize + lLeftOver
        sFileData = DaoRs(sField).GetChunk(lStartByte, iBlockSize)
        If bWriteToFile Then
            Put #iFreeFile, , sFileData
        Else
            If (Len(sDestination) + Len(sFileData)) < 32000 Then
                sDestination = sDestination & sFileData
            Else
                bTooLong = True
            End If
        End If
    
    Next i
    
    If bWriteToFile Then
        Close #iFreeFile
    End If
    
    ManageMemoField = Not bTooLong
    Exit Function
     
    Lbl_Err:
    ManageMemoField = False
    Exit Function
     
    End Function

    Personalmente non condivido il voler salvare i PDF dentro un DB però riconosco che avendo MySQL (con motore myisam) non dovresti avere i problemi che hai sicuramente con Access (a cominciare dal limite dei 2GB per database) …

  • Re: Campi BLOB MySql e file Pdf

    19/11/2024 - Catafirro ha scritto:


    Trovato, era semplicissimo, si fa attraverso MySql stesso

    SELECT PdfBlob INTO DUMPFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/test.pdf' FROM tila_20241108_pdf.tblinvpb_pdf;

    Meglio così …

  • Re: Campi BLOB MySql e file Pdf

    Personalmente non condivido il voler salvare i PDF dentro un DB però riconosco che avendo MySQL (con motore myisam) non dovresti avere i problemi che hai sicuramente con Access (a cominciare dal limite dei 2GB per database) …

    Ti ringrazio per il codice che mi studio, anche se il problema pare si risolva “secondo natura".

    La mia gestione dei PDF attraverso campi BLOB è una pensata degli ultimi giorni, che potrebbe rivelarsi vincente, anche se confesso che non ne sono ancora del tutto sicuro. Questi Pdf vengono generati dal mio applicativo attraverso una chiamata a WORD, che ha in pasto dei modelli e delle tabelle access, ne fa un merge e alfine genera sia DOCX e/o PDF alla bisogna. Tali documenti sono associati a un record (fai conto una fattura) e servono soprattutto per essere inviati via mail come allegati. Ho pensato che invece di averli su disco con dentro il record il loro indirizzo (potrebbero essere cancellati, spostati, eliminati) potrebbe essere meglio averli su un campo BLOB, dal quale possono in ogni momento essere ritrasferiti su disco, utilizzati e poi di nuovo eliminati.

    Per evitare i problemi di MySql con i campi BLOB (io ne ho avuti in passato al momento di backup e restore) ho pensato di creare un database collaterale in cui, per ogni tabella che nel principale ha bisogno di un BLOB, ho una tabella con lo stesso nome e un record con la stessa chiave e il solo campo BLOB. Visto che non hanno bisogno di transazioni, queste tabelle sono del tipo MyIsam, più semplici e di più facile backup. In ogni caso la perdita dei BLOB non costituirebbe un grave problema, essendo comunque ricreabili. Il vantaggio di questa separazione è che il db principale è privo degli appesantimenti dovuti ai BLOB.  

  • Re: Campi BLOB MySql e file Pdf

    19/11/2024 - Catafirro ha scritto:


    La mia gestione dei PDF attraverso campi BLOB è una pensata degli ultimi giorni, che potrebbe rivelarsi vincente, anche se confesso che non ne sono ancora del tutto sicuro. Questi Pdf vengono generati dal mio applicativo attraverso una chiamata a WORD, che ha in pasto dei modelli e delle tabelle access, ne fa un merge e alfine genera sia DOCX e/o PDF alla bisogna. Tali documenti sono associati a un record (fai conto una fattura) e servono soprattutto per essere inviati via mail come allegati. Ho pensato che invece di averli su disco con dentro il record il loro indirizzo (potrebbero essere cancellati, spostati, eliminati) potrebbe essere meglio averli su un campo BLOB, dal quale possono in ogni momento essere ritrasferiti su disco, utilizzati e poi di nuovo eliminati.

    Per evitare i problemi di MySql con i campi BLOB (io ne ho avuti in passato al momento di backup e restore) ho pensato di creare un database collaterale in cui, per ogni tabella che nel principale ha bisogno di un BLOB, ho una tabella con lo stesso nome e un record con la stessa chiave e il solo campo BLOB. Visto che non hanno bisogno di transazioni, queste tabelle sono del tipo MyIsam, più semplici e di più facile backup. In ogni caso la perdita dei BLOB non costituirebbe un grave problema, essendo comunque ricreabili. Il vantaggio di questa separazione è che il db principale è privo degli appesantimenti dovuti ai BLOB.  

    Tenere tutto separato sicuramente aiuta, però essendo documenti che puoi sempre ricreare, io non farei tutto questo ‘castello’ e mi accontenterei di averli su disco, salvando nel DB in un campo testo il nome del file (ed eventualmente il percorso nello stesso campo o in un campo separato).

    Avrei pensato ad un ‘castello’ simile per ‘proteggere’ i documenti anche dalla semplice visualizzazione e/o per garantirne l'integrità rendendo più complicata la loro modifica.

  • Re: Campi BLOB MySql e file Pdf

    In effetti è quello che fa la vecchia applicazione, ma voglio esplorare questa strada, magari mi pento, poi ti dirò.

Devi accedere o registrarti per scrivere nel forum
6 risposte