Writing and reading binary data

Please import the Client API test data for the following example. We will now create a new data object with binary data in the onion.net Information Server.

using System;
using System.IO;
using System.Xml.Linq;
using Onion.Client;

class Program
{
  static void Main(string[] args)
  {
    using (var session = new OnionSession("ipc://onion.net/onion/server", "admin", "admin"))
    {
      IDataObject contacts = session.Repository.Lookup("Client API Testdata", "1. Contacts");

      // first we make the picture available on the server
      ITemporaryBinaryObject picture = session.Repository.CreateBinary("image/jpeg");

      using (var target = picture.CreateStream())
      using (var source = File.OpenRead(@"C:\Testdaten\Erika.jpg"))
      {
        CopyStream(source, target);
      }

      XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";

      // by the use of the temporary binary reference, it gets persisted along with the data object
      var el = new XElement("person",
        new XAttribute(XNamespace.Xmlns + "xsi", xsi),
        new XAttribute(xsi + "schemaLocation", "http://onion.net/examples/client-api/contacts/person"),
        new XAttribute("gender", "female"),
        new XElement("picture", picture.ReferenceIdentifier)
      );

      IDataObject newContact = contacts.Children.Create("Erika Mustermann", el.ToString());

      Console.WriteLine(String.Format("New data object {0} created on {1}.",
        newContact.Id, newContact.DateCreated));
    }
  }

  private static void CopyStream(Stream source, Stream target)
  {
    int bytesRead;
    var buffer = new byte[32768];

    while ( (bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
    {
      target.Write(buffer, 0, bytesRead);
    }
  }
}

In onion.net there is no physical file system and therefore no file references for binary data. Instead, onion.net makes it possible to embed binary data into data objects. The number of binary objects in a data object is not limited, as is normally the case in XML.. However, for reasons of efficiency, they are not saved as a Base64-coded string within the Xml document, but held ready in an administrated binary data memory.

In the above example, a volatile binary data object (ITemporaryBinaryObject) is created, filled with data from a file and then transferred as part of the new data object. onion.net automatically converts the volatile binary data objects into persistent binary data. The following example shows how the binary data on the other hand can be read out:

using System;
using System.Xml.Linq;
using Onion.Client;

class Program
{
  static void Main(string[] args)
  {
    using (var session = new OnionSession("ipc://onion.net/onion/server", "admin", "admin"))
    {
      IDataObject dataObject = session.Repository.Lookup("Client API Testdata", "1. Contacts", "Erika Mustermann");

      var doc = XDocument.Load(dataObject.CreateXmlReader());

      IBinaryObject picture = dataObject.GetBinary(doc.Element("person").Element("picture").Value);
     
      using (Stream source = picture.CreateStream())
      {
        Console.WriteLine(String.Format("Binary {0} with mimetype {1} has a length of {2} bytes.",
          picture.ReferenceIdentifier, picture.MimeType, source.Length));
      }
    }
  }
}

The data object "Erika Mustermann" is addressed via the “Lookup” method. The binary data reference is extracted from the Xml document and access to the binary data finally takes place via the method “IDataObject.GetBinary”. The example should lead to a result similar to this:

Binary onion://data/binaries/3 with mimetype image/jpeg has a length of 770042 bytes.