Binary content

Table of Contents

20.1. Introduction
20.2. Standard blob management
20.3. External blob management
20.4. About BlobHolder

20.1. Introduction

Special kinds of field types can be used to manage binary content. Here is a presentation about how to set them up in custom document types.

20.2. Standard blob management

The standard binary content is defined in the Nuxeo core types that are deployed by default. It is handled by the repository. If the binary content is stored on the file system or in the SQL backend is up to the repository configuration.

To create a new binary field, you can include this file in your schema definition and refer to the type named "content".

WARNING : any type named "content" will be handled as a binary type, so this field named should be considered as reserved.

Sample declaration of a binary field:

<xs:schema targetNamespace="http://www.nuxeo.org/ecm/schemas/binary_content_sample/"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:nxs="http://www.nuxeo.org/ecm/schemas/binary_content_sample/">

  <xs:include schemaLocation="core-types.xsd" />

  <xs:element name="my_attached_file" type="nxs:content" />

</xs:schema>

Defining this field will make it possible to set and get a Blob for this property value.

Let's have a look at the content field definition:

<xs:complexType name="content">
  <xs:sequence>
    <xs:element name="encoding" type="xs:string" />
    <xs:element name="mime-type" type="xs:string" />
    <xs:element name="data" type="xs:base64Binary" />
    <xs:element name="name" type="xs:string" />
    <xs:element name="length" type="xs:long" />
    <xs:element name="digest" type="xs:string" />
  </xs:sequence>
</xs:complexType>

The blob holds a number of additional properties that give additional information about the blob content. These fields can be retrieved and set through the blob api. Some of them are automatically set by some nuxeo default events.

Note that the file name is also stored in the blob. As it was not originally the case, the default "file" schema defines a string field to hold it. It is the one used by default, but some listeners do copy this value to the blob file name sub property.

20.3. External blob management

External blobs are available since release 5.2.1. Although their retrieval is also handled through the repository and Nuxeo core API, the way to retrieve them can be customized.

For instance, the default FileSystemExternalBlobAdapter plugin makes it possible to refer to files that are stored in a different file system folder than the one handled by the repository. This can be handy if you already have a set of files available on your system and would like to avoid dupplicating these files when using them in your Nuxeo application.

To create an external binary field, you can include the Nuxeo core types file in your schema definition and refer to the type named "externalcontent".

WARNING : any type named "externalcontent" will be handled as a binary type, so this field named should be considered as reserved.

Sample declaration of a binary field:

<xs:schema targetNamespace="http://www.nuxeo.org/ecm/schemas/binary_content_sample/"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:nxs="http://www.nuxeo.org/ecm/schemas/binary_content_sample/">

  <xs:include schemaLocation="core-types.xsd" />

  <xs:element name="my_external_file" type="nxs:externalcontent" />

</xs:schema>

If you would like to refer to files on the file system, on the same server than the one holding the repository, you can use the following configuration:

<?xml version="1.0"?>

<component name="org.nuxeo.ecm.core.api.externalblob.adapter.sample">
  <documentation>
    External blob sample contribution: a file system adaptor that takes the
    "container" property to set the absolute path of the container folder on the
    file system.
  </documentation>

  <extension
    target="org.nuxeo.ecm.core.api.blobholder.BlobHolderAdapterComponent"
    point="ExternalBlobAdapter">
    <adapter prefix="fs"
      class="org.nuxeo.ecm.core.api.externalblob.FileSystemExternalBlobAdapter">
      <property name="container">/path/to/my/container</property>
    </adapter>
  </extension>

</component>

Note that you have to define the container folder, and a prefix for this configuration. These properties will be used to build the corresponding blob: the repository only stores an URI that looks like "fs:/subfolder/myfile.txt". After the prefix, we can see the file path, relative to the container folder. The file system adapter will then be able to retrieve the blob will all this information. Configuring the container property independantly from what the repository stores makes it possible to change the container folder place in the file system.

When creating an external blob, you have to build this uri as it is the only information that will be handled by the current system: uploading a file, building the corresponding uri and putting the corresponding file on the file system is not supported.

Here is some sample code to setup an external blob:

DocumentModel doc = ...
String uri = "fs:/subfolder/myfile.txt";
doc.setPropertyValue("my_schema:my_external_file/uri", uri);
...
Blob blob = (Blob) doc.getPropertyValue("my_schema:my_external_file");

Let's have a look at the external content field definition:

<xs:complexType name="content">
  <xs:sequence>
    <xs:element name="encoding" type="xs:string" />
    <xs:element name="mime-type" type="xs:string" />
    <xs:element name="uri" type="xs:string" />
    <xs:element name="name" type="xs:string" />
    <xs:element name="length" type="xs:long" />
    <xs:element name="digest" type="xs:string" />
  </xs:sequence>
</xs:complexType>

You can see that it is very similar to the standard blob, except taht the data is replaced by a string URI. As long as the uri is set, the additional fields can be retrieved and set through the blob api. Some of them are automatically set by some nuxeo default events, similarly to what's done for a standard blob. The external blob content indexing is also handled so that a document can be found searching on keywords present in the referred file.

If you'd like to define your own way of retrieving a file (for instance, connect to a FTP server or get it from the web), you can write an new class following the ExternalBlobInterface, and register it to the "ExternalAdapter" extension point, as shown above for the fiel system adapter. You will have to use your own prefix so that the system knows what adapter to use to retrieve the file.

20.4. About BlobHolder

BlobHolder defined an abstract interface for objects that can hold one or several blobs. BlobHolders can be created from plain Blob (or List<Blob>) or from a DocumentModel. Compared to a plain Blob, a BlobHolder provides lazy loading of a blob when possible and keeps track of the link between the Blob and the DocumentModel. In fact, BlobHolder interface is also available as a DocumentModelAdapter, so you can simply get a BlobHolder from a DocumentModel. Using BlobHolder provides several advantages :

  • no more need to hardcode the xpath to extract the blob from a DocumentModel (this is done once and for all in the DocumentModelAdapter configuration)

  • conversionservice caching system can no efficiently monitor changes

# create a BlobHolder from a File

File file = ...
Blob blob = new FileBlob(file);
BlobHolder fileBlobHolder = new SimpleBlobHolder(blob);

# get BlobHolder from a Document

DocumentModel myDoc = ...
BlobHolder docBlobHolder = myDoc.getAdapter(BlobHolder.class);

# create a BlobHolder "by hand" on top of a DocumentModel

BlobHolder docBlobHolder2 = new DocumentBlobHolder(myDoc, "file:content");