Comment stocker une image dans une base de données ?
Avant toute chose, il faut savoir qu'il est totalement déconseillé de
stocker des images dans une base de données. C'est très lourd, absolument
inutile et cela peut même ralentir le serveur de données. Il ne faut pas
perdre de vue que le but premier d'une base de données est de stocker des
données à des fins de recherches, d'indexages ou de calculs. Ce qui n'a
absolument aucune application dans le cas d'images. En bref, mieux vaut toujours
stocker à la place le chemin (relatif, absolu, distant, ...) de l'image.
Néanmoins, si vous désirez quand même stocker une image dans une base de
données, nous allons passer en revue les différentes techniques.
Tout d'abord, prenons le cas particulier d'Access qui permet, par le biais
d'un champ de type OLE, de stocker des images. Cette solution, très pratique au
sein même d'Access, l'est nettement moins lorsqu'il s'agit de récupérer les
images dans Visual Basic. En effet, il vous sera impossible de lier ce champ à
un contrôle "Image" ou "PictureBox". Tout simplement car on
n'a plus affaire à une image, mais bien à un objet OLE. Remarquez au passage
qu'il ne faut pas s'étonner si la taille de l'image stockée est supérieure à
la taille de l'image d'origine, l'interface OLE rajoutant toute une série
d'en-têtes (cfr. 123151
- ACC : Pourquoi les objets OLE font augmenter la taille des bases de données).
Comment faire donc pour récupérer les images encapsulées dans un objet OLE.
Deux solutions. La première est d'employer le contrôle "OLE" (livré
en standard avec VB). Malheureusement, celui-ci ne peut être lié qu'à une source
de données utilisant la technologie DAO. Si vous employer ADO, c'est râpé. La
deuxième solution consiste à extraire, de l'objet OLE, l'image encapsulée.
Pour ce faire, vous pouvez vous baser sur l'exemple décrit dans la fiche
suivante : 119395
- How to Extract the Metafile from an OLE Control.
Vous l'aurez donc compris, OLE n'est pas vraiment la solution pour stocker
des images. L'idéal est en fait de stocker les images sous forme binaire. Et
cela vaut non seulement pour Access, mais aussi pour tout les autres types de
base de données (Oracle, SQL Server, ...). Pour cela il faudra employer les
méthodes AppendChunk et GetChunk qui permettent de lire et écrire des données
binaires dans un champ de type binaire (équivalent au type "OLE" pour
Access et "blob" pour SQL Server). Vous trouverez plusieurs exemples
sur la MSDN et le site du support :
Enfin, si vous utiliser une version d'ADO supérieure ou égale à 2.5, vous
pouvez employer l'objet Stream qui facilite grandement les opérations de
lectures et écritures sur des champs binaires. Ce code permet, par exemple,
d'écrire le contenu d'un fichier dans un champ binaire :
Option Explicit
Private Sub Form_Load()
Dim rs As ADODB.Recordset
Dim stm As ADODB.Stream
Set rs = New ADODB.Recordset
Set stm = New ADODB.Stream
rs.Open "Table1",
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Mes
Documents\MyDataBase.mdb", adOpenStatic, adLockOptimistic, adCmdTable
stm.Type = adTypeBinary
stm.Open
stm.LoadFromFile "C:\Mes Documents\Photo.bmp"
rs.AddNew
rs!Nom = "Pierre Alexis"
rs!Photo = stm.Read
rs.Update
rs.Close
stm.Close
Set rs = Nothing
Set stm = Nothing
End Sub
Ensuite, pour récupérer cette image et l'afficher dans Visual Basic, le
plus simple consiste à lier un contrôle Image à ce champ (en passant par un
contrôle ADODC ou bien en liant un recordset par le code).
Si vous désirez récupérer l'image "manuellement" sans passer par
une liaison de champ, la solution la plus simple (mais pas la plus performante),
consiste à passer par un fichier temporaire et à employer ensuite la fonction
LoadPicture de VB :
Option Explicit
Private Declare Function GetTempFileName Lib "kernel32" Alias
"GetTempFileNameA" (ByVal lpszPath As String, ByVal lpPrefixString As
String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
Private Declare Function GetTempPath Lib "kernel32" Alias
"GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String)
As Long
Private Const MAX_PATH = 260
Private Sub Form_Load()
Dim rs As ADODB.Recordset
Dim stm As ADODB.Stream
Dim sTemporyFileName As String
Set rs = New ADODB.Recordset
Set stm = New ADODB.Stream
rs.Open "SELECT Photo FROM Table1 WHERE Nom = 'Pierre
Alexis'", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Mes
Documents\MyDataBase.mdb", adOpenStatic, adLockOptimistic, adCmdText
stm.Type = adTypeBinary
stm.Open
stm.Write rs.Fields("Photo").Value
sTemporyFileName = GenerateTemporyFileName("PGM")
stm.SaveToFile sTemporyFileName, adSaveCreateOverWrite And
adSaveCreateNotExist
Set Image1.Picture = LoadPicture(sTemporyFileName)
Kill sTemporyFileName
rs.Close
stm.Close
Set rs = Nothing
Set stm = Nothing
End Sub
' Cette fonction permet de récupérer le chemin du dossier temporaire de
Windows
' et d'ensuite générer un nom de fichier valide (càd qui n'existe pas encore)
' Le paramètre Prefix est une chaîne dont les trois premières lettres seront
' reprises comme initiales du fichier temporaire.
Public Function GenerateTemporyFileName(Optional Prefix As String =
"TMP") As String
Dim sBuffer As String
Dim sTempFolderPath As String
' Initialisation des buffers
sTempFolderPath = String$(MAX_PATH, Chr$(0))
sBuffer = String$(MAX_PATH - 14, Chr$(0))
If GetTempPath(MAX_PATH, sTempFolderPath) Then
If GetTempFileName(sTempFolderPath,
Prefix, 0&, sBuffer) Then
GenerateTemporyFileName = Left$(sBuffer, InStr(1, sBuffer, Chr$(0)) - 1)
End If
End If
End Function
Concernant l'utilisation de l'objet Stream, vous pouvez aussi lire cette
fiche : 258038
- HOWTO: Access and Modify SQL Server BLOB Data by Using the ADO Stream Object. |