Serializar Imagenes en XML Fecha: 17/Ago/2004 (17/Ago/2004) |
Muchas veces he tenido problemas sobre la mejor forma de almacenar las imágenes o cualquier otro elemento binario tanto en base de datos como en un archivo plano, sobre todo porque no siempre puedo utilizar la misma rutina para todos los casos. Como en mis proyecto uso XML extensivamente, se me ocurrió utilizarlo como herramienta de almacenamiento para muchas cosas y especialmente para imágenes y datos binarios, ya que me permiten llevar este documento como texto plano a cualquier base de datos en forma de String sin ningún problema, y obviamente puedo utilizar la misma rutina en todos los casos.
Tengo una Clase llamada Serialization que contiene dos (2) metodos Shared:
- ImageToXMLNode: Persiste la imagen en XML y retorna el Nodo XML con la Imagen serializada.
- XMLNodeToImage: Desserializa la imagen almacenada y la retorna como bitmap.
Aqui esta el codigo comentado de las funciones:
'Serializa Imagen en XMLPublic Shared Function ImageToXMLNode(ByVal Image As Image) As Xml.XmlNode Dim oStream As New System.IO.MemoryStream Dim oDom As New Xml.XmlDocument Dim mResult As New IO.MemoryStream Dim LenData As Long = 0 Dim Buffer() As Byte Dim oBinaryReader As IO.BinaryReader Dim oXMLTextWriter As Xml.XmlTextWriter Dim oStreamReader As IO.StreamReader Dim StrResult As String 'Verifico si existe imagen a serializar If Not Image Is Nothing Then 'Se graba en Stream para almacenar la imagen en formato binario Image.Save(oStream, System.Drawing.Imaging.ImageFormat.Bmp) oStream.Position = 0 LenData = oStream.Length - 1 'Verifico la longitud de datos a serializar If LenData > 0 Then ReDim Buffer(LenData) 'Genero Buffer 'Leo los datos binarios oBinaryReader = New IO.BinaryReader(oStream, System.Text.Encoding.UTF8) oBinaryReader.Read(Buffer, 0, Buffer.Length) 'Creo XMLTextWriter y agrego nodo con la imagen oXMLTextWriter = New Xml.XmlTextWriter(mResult, System.Text.Encoding.UTF8) oXMLTextWriter.WriteStartDocument() oXMLTextWriter.WriteStartElement("BinaryData") oXMLTextWriter.WriteBase64(Buffer, 0, Buffer.Length) oXMLTextWriter.WriteEndElement() oXMLTextWriter.WriteEndDocument() oXMLTextWriter.Flush() 'posiciono en 0 el resultado mResult.Position = 0 'Pasa el Stream a String y retorna oStreamReader = New IO.StreamReader(mResult, System.Text.Encoding.UTF8) StrResult = oStreamReader.ReadToEnd() oStreamReader.Close() 'Agrego Nuevo Nodo con imagen oDom.LoadXml(StrResult) Return oDom.DocumentElement Else 'En caso de no existir datos retorno el XML con formato vacio oDom.LoadXml("<BinaryData/>") Return oDom.DocumentElement.CloneNode(True) End If Else 'no hay imagen devuelvo el XML Vacio oDom.LoadXml("<BinaryData/>") Return oDom.DocumentElement.CloneNode(True) End If End Function 'Desserializa XML y retorna la Imágen Public Shared Function XMLNodeToImage(ByVal Nodo As Xml.XmlNode) As Image Dim IntResult As Integer = 0 Dim IntPosition As Integer = 0 Dim LenBytes As Integer = 1024 * 1024 '1024KB - 1MB Lee bloques de 1MB Dim myBytes(LenBytes - 1) As Byte Dim oMem As New IO.MemoryStream Dim oXMLTextReader As Xml.XmlTextReader Dim NodeFound As Boolean = False Dim oStreamReader As IO.StreamReader Dim oStreamWriter As IO.StreamWriter Dim oTempMem As New IO.MemoryStream Try 'Cargo nodo de texto en Memory Stream para almacenar la imagen temporalmente en bytes oStreamWriter = New IO.StreamWriter(oTempMem, System.Text.Encoding.UTF8) oStreamWriter.Write(Nodo.OuterXml) oStreamWriter.Flush() oTempMem.Position = 0 'Cargo un xmlReader con el Memory Stream para leer la imágen almacenada oXMLTextReader = New Xml.XmlTextReader(oTempMem) 'Busco el Nodo en Binario Do While oXMLTextReader.Read If oXMLTextReader.Name = "BinaryData" Then NodeFound = True Exit Do End If Loop 'Verifico si se encontró el Nodo con la imagen If NodeFound Then 'Lo encontro, me muevo a la Posicion Inicial del Stream para leerlo IntPosition = 0 'Intento Leer IntResult = oXMLTextReader.ReadBase64(myBytes, 0, LenBytes) Do While IntResult > 0 'Escribe datos oMem.Write(myBytes, 0, IntResult) 'Limpio el array Array.Clear(myBytes, 0, LenBytes) 'Leo nuevamente IntResult = oXMLTextReader.ReadBase64(myBytes, 0, LenBytes) Loop Try 'Intento crear la Imagen y retornarla si no devuelvo Nothing Dim oBitmap As New Bitmap(oMem) Return oBitmap Catch Return Nothing End Try Else 'No encontró el nodo de imágen Return Nothing End If Catch ex As Exception 'Ocurrio un error no contemplado Retorno Nothing Return Nothing End Try End Function 'Funcion Auxiliar para agregar un nodo a otro Private Shared Sub AddElement(ByRef pParentNode As Xml.XmlNode, ByVal pNewNodeName As String, ByVal pNewNodeValue As String) Dim oNodo As Xml.XmlNode oNodo = pParentNode.OwnerDocument.CreateElement(pNewNodeName) oNodo.InnerText = pNewNodeValue pParentNode.AppendChild(oNodo.CloneNode(True)) oNodo = Nothing End SubPara utilizar estas rutinas basta con llamarlas desde cualquier lugar del codigo y se obtiene una imagen o un nodo XML con la imagen serializada lista para ser guardada en una base de datos, en un archivo plano o bien para trasmitirse via WebService a donde se necesite.
Espero que les sea útil.
Saludos.
Fichero con el código de ejemplo: cbigentini_SerializarImagenesEnXML.zip - 52 KB