how to send binary data within an xml string
Asked Answered
M

4

7

I want to send a binary file to .net c# component in the following xml format

<BinaryFileString fileType='pdf'>
    <!--binary file data string here-->
</BinaryFileString>

In the called component I will use the above xml string and convert the binary string received within the BinaryFileString tag, into a file as specified by the filetype='' attribute. The file type could be doc/pdf/xls/rtf

I have the code in the calling application to get out the bytes from the file to be sent. How do I prepare it to be sent with xml tags wrapped around it? I want the application to send out a string to the component and not a byte stream. This is because there is no way I can decipher the file type [pdf/doc/xls] just by looking at the byte stream. Hence the xml string with the filetype attribute. Any ideas on this?

method for extracting Bytes below

   FileStream fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
   using (Stream input = fs)
   {
      byte[] buffer = new byte[8192];
      int bytesRead;
      while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
      {}
   }
   return buffer;

Thanks.

Edit:

Just to clarify why I am using an xml string rather than setting properties on my component. Actually my calling app is trying to simulate how Siebel will call my component. http://download.oracle.com/docs/cd/E05553_01/books/eScript/eScript_JSReference244.html#wp1014380 Im not sure if Siebel can set my components properties as I need it to. So Im working on the angle of it sending the data in xml.

Mediatize answered 31/5, 2010 at 3:41 Comment(1)
Why do you need to wrap your binary data in xml?Anniceannie
J
9

Base64 representation is universaly used to represent binary data.

public void EncodeWithString() {
    System.IO.FileStream inFile;     
    byte[] binaryData;

    try {
        inFile = new System.IO.FileStream(inputFileName,
                                          System.IO.FileMode.Open,
                                          System.IO.FileAccess.Read);
        binaryData = new Byte[inFile.Length];
        long bytesRead = inFile.Read(binaryData, 0,
                                    (int)inFile.Length);
        inFile.Close();
    }
    catch (System.Exception exp) {
        // Error creating stream or reading from it.
        System.Console.WriteLine("{0}", exp.Message);
        return;
    }

    // Convert the binary input into Base64 UUEncoded output.
    string base64String;
    try {
         base64String = 
            System.Convert.ToBase64String(binaryData, 
                                          0,
                                          binaryData.Length);
    }
    catch (System.ArgumentNullException) {
        System.Console.WriteLine("Binary data array is null.");
        return;
    }

    // Write the UUEncoded version to the XML file.
    System.IO.StreamWriter outFile; 
    try {
        outFile = new System.IO.StreamWriter(outputFileName,
                                    false,
                                    System.Text.Encoding.ASCII);             
        outFile.Write("<BinaryFileString fileType='pdf'>");
        outFile.Write(base64String);
        outFile.Write("</BinaryFileString>");
        outFile.Close();
    }
    catch (System.Exception exp) {
        // Error creating stream or writing to it.
        System.Console.WriteLine("{0}", exp.Message);
    }
}

At the receiving end you can reverse this and get back original file content as mentioned below.

        // Convert the Base64 UUEncoded input into binary output.
        byte[] binaryData;
        try {
            binaryData = 
                System.Convert.FromBase64String(base64String);
        }
        catch (System.ArgumentNullException) {
            System.Console.WriteLine("Base 64 string is null.");
            return;
        }
        catch (System.FormatException) {
            System.Console.WriteLine("Base 64 string length is not " +
                "4 or is not an even multiple of 4." );
            return;
        }
Juliannajulianne answered 31/5, 2010 at 5:39 Comment(3)
tiny nitpick: UUEncoding and Base64 are two different things. en.wikipedia.org/wiki/Uuencoded en.wikipedia.org/wiki/Base64Bunkmate
@Bunkmate True, but documentation such as Convert.ToBase64String don't help (check the Remarks section ;-).Gardy
I would only note that saying Base64 is a "universal" method is not accurate. I'm currently running into some fun issues creating XML with an embedded TIF. It needs to mimic another interface from a vendor whose source code I don't have access to. However, they literally bump the binary into the XML - not Base64 encoded at all. I've seen this in other circumstances in other industries as well. It's probably the SMARTEST way to go, but it's far from universal.Caslon
B
4

Can you BASE64 your bytes? MSDN ref: Convert.ToBase64, Convert.FromBase64String

Bunkmate answered 31/5, 2010 at 3:52 Comment(4)
how do I convert it back? Once converted to string, the bytes cant be used to recreate the file, right?Mediatize
Convert.FromBase64String will convert the string back to a byte arrayBunkmate
Thank you! I was planning to soon use Cryptography.FromBase64Transform because I didn't know about these easier methods.Sympathin
Thanks Russau-will try this out.Mediatize
L
3

expanding on @russau's answer it will work like this:

var s = "Hello World";
var b = Encoding.Default.GetBytes(s);
var bstr = Convert.ToBase64String(b);
Console.WriteLine("Original String:" + s);
Console.WriteLine("Base64 String:" + bstr);

var fromBStr = Convert.FromBase64String(bstr);
var st = Encoding.Default.GetString(fromBStr);
Console.WriteLine("Converted string: " + st);

you wont need first two lines:

var s = "Hello World";
var b = Encoding.Default.GetBytes(s);

as you already have a byte array. I've used string to show that you get exactly the same value you started with in the end when you convert byte array from Convert.FromBase64String

Lawler answered 31/5, 2010 at 4:9 Comment(0)
R
0

You mention that you are calling a C# component. I'm not sure I understand why using this component means you need to create an XML string.

Is it possible to define classes to hold your data instead of using an XML string? e.g.

public enum FileType
{
    Word,
    Excel,
    RichText,
    PDF
}

public class FileData
{
    public FileType TypeOfFile
    {
        get;
        set;
    }

    public byte[] Data
    {
        get;
        set;
    }
}

Then the caller of the component just sets the FileType and the byte[]. The component's interface would then be more explicitly defined (FileData class as opposed to the more generic string or XmlDocument).

Recycle answered 31/5, 2010 at 5:29 Comment(1)
Thanks Tuzo. actually my calling app is trying to simulate how Siebel will call my component. download.oracle.com/docs/cd/E05553_01/books/eScript/… Im not sure if it can set my components properties as I need it to. So Im working on the angle of it sending the data in xml.Mediatize

© 2022 - 2024 — McMap. All rights reserved.