Solved

Getting Image Data From XML

Posted on 2004-08-25
3
782 Views
Last Modified: 2012-06-27
I have image data stored in an XML file using bin.base64 encoding. The xml file is as follows:
=========
<userPhotos>
<Photo>
  <UserID>1</UserID>
  <UserName>Camel-Joe</UserName>
  <PhotoContent xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="bin.base64">/9j/4AAQSkZJRgABAgEBLAEsAAD/4RV2RXhpZgAA</PhotoContent>
  </Photo>
</UserPhotos>
=========

i also have a user control which takes a byte() object as input and outputs an image. When i get the xml value from the xml file and pass it to this control, i get an error of "Invalid parameter used."

======  Image User Control
    Protected Friend Sub ImageByByte(ByVal sByte As Byte())
        If (Not sByte Is Nothing) Then
            Response.ContentType = "image/jpg"
            Response.Clear()
            Dim iStream As New System.IO.MemoryStream(sByte, True)
            iStream.Write(sByte, 0, sByte.Length)
            sByte = Nothing

            Dim fullImg As Bitmap = New Bitmap(iStream)
            fullImg = System.Drawing.Image.FromStream(iStream)
            iStream = Nothing

            fullImg.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
            fullImg.Dispose()
            fullImg = Nothing
        End If
        Me.Dispose()
    End Sub
======


here's how i get the xml data and pass it to the control
=========
    Private Function xmlPhoto(ByVal userName As String) As Byte()
        Dim xDoc As New XmlDocument(), xNode As XmlNode
        Dim asc As New System.Text.ASCIIEncoding()

        Try
            xDoc = New XmlDocument()
            xDoc.Load("c:\inetpub\wwwRoot\UserPhotos.xml")
            xNode = xDoc.SelectSingleNode("//Photo[UserName = '" & userName & "']")
            xmlPhoto = asc.GetBytes(xNode.Item("PhotoContent").InnerText)
        Finally
            asc = Nothing
            xDoc = Nothing
            xNode = Nothing
        End Try
    End Function
=========


If i pass the byte data to the control directly from a sql table (where images are also stored) there's no problem. so i'm doing something wrong in grabbing the image data from xml.

xNode.Item("PhotoContent").InnerText returns the correct xml element value.
xmlPhoto.GetType returns System.Byte[].  
xmlPhoto.length also returns an integer value >  0.

Any help would be greatly appreciated. thanks.


0
Comment
Question by:jklNYC
  • 2
3 Comments
 
LVL 26

Expert Comment

by:rdcpro
ID: 11896962
Use nodeTypedValue, something more or less like:

            xNode = xDoc.SelectSingleNode("//Photo[UserName = '" & userName & "']")
            xmlPhoto = xNode.nodeTypedValue

Darshan Singh had a good article on doing this:

http://www.perfectxml.com/articles/xml/binary.asp

Regards,
Mike Sharp
0
 
LVL 2

Author Comment

by:jklNYC
ID: 11897042
Mike,

Yeah I've tried to use the nodetypedvalue and it doesn't work. i get this error on compile
"img.aspx.vb(82): 'nodetypedvalue' is not a member of 'System.Xml.XmlNode'."

I've read that article, and I am unable to use the following lines:

Dim oXMLDOMDoc As New MSXML2.DOMDocument40
Dim oNode As MSXML2.IXMLDOMNode

The server won't recognize those object declarations. Am I missing something on the server? Do i need to install another XML library object?

.jkl.

0
 
LVL 26

Accepted Solution

by:
rdcpro earned 250 total points
ID: 11897251
Oh, I didn't know you were using .NET.  You might be able to use the XmlTextReader.ReadBase64 method, which reads a base64 encoding stream and fills a byte array buffer.  It returns the number of bytes written to the buffer.

Public Function ReadBase64( _
   ByVal array() As Byte, _
   ByVal offset As Integer, _
   ByVal len As Integer _
) As Integer

Parameters

  array
    The array of characters that serves as the buffer to which the text contents are written.
  offset
    The zero-based index into the array specifying where the method can begin to write to the buffer.
  len
    The number of bytes to write into the buffer.
  Return Value
    The number of bytes written to the buffer.

Remarks

Like ReadChars, this method can be called successively to read large streams of embedded text. It decodes Base64 content and returns the decoded binary bytes (for example, an inline Base64 encoded GIF image) into the buffer. See RFC 1521. (You can obtain RFCs from the Request for Comments Web site at http://www.rfc-editor.org)




Here's a C# example that does basically the same thing:


XmlTextReader reader = new XmlTextReader(filename);
while(reader.Read()) {
  if (reader.LocalName == "element") {
    byte[] bytes = new byte[1000];
    int n = reader.ReadBase64(bytes, 0, 1000);
    string buf = Encoding.Unicode.GetString(bytes);
    Console.WriteLine(buf.Substring(0,n));
  }
}
reader.Close();

And, a VB.NET example from MSDN:

[Visual Basic, C#, C++] The following example reads a file containing Base64 and BinHex data.

[Visual Basic]
Option Explicit
Option Strict

Imports System
Imports System.IO
Imports System.Xml
Imports Microsoft.VisualBasic

Public Class Sample
   Private Const filename As String = "binary.xml"
   
   
   Public Shared Sub Main()
      Dim reader As XmlTextReader = Nothing
      Dim i As Integer

      Try
         reader = New XmlTextReader(filename)
         reader.WhitespaceHandling = WhitespaceHandling.None        

         ' Read the file. Stop at the Base64 element.        
         While reader.Read()
            If "Base64" = reader.Name Then
               Exit While
            End If
         End While

         ' Read the Base64 data. Write the decoded
         ' bytes to the console.
         Console.WriteLine("Reading base64... ")
         Dim base64len As Integer = 0
         Dim base64(1000) As Byte
         Do
            base64len = reader.ReadBase64(base64, 0, 50)
            For i = 0 To base64len - 1
               Console.Write(base64(i))
            Next i
         Loop While (reader.Name = "Base64")

         ' Read the BinHex data. Write the decoded
         ' bytes to the console.
         Console.WriteLine(ControlChars.CrLf & "Reading binhex....")
         Dim binhexlen As Integer = 0
         Dim binhex(1000) As Byte
         binhexlen = reader.ReadBinHex(binhex, 0, 50)
         Do
            binhexlen = reader.ReadBinHex(binhex, 0, 50)
            For i = 0 To binhexlen - 1
               Console.Write(binhex(i))
            Next i
         Loop While (reader.Name = "BinHex")
     
      Finally
         Console.WriteLine()
         Console.WriteLine("Processing of the file {0} complete.", filename)
         If Not (reader Is Nothing) Then
            reader.Close()
         End If
      End Try
   End Sub 'Main
End Class 'Sample


Regards,
Mike Sharp
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
This video discusses moving either the default database or any database to a new volume.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now