Use plone.app.blob-based BLOB storage

by Plone Documentation Team last modified Dec 08, 2010 10:34 AM
Plone 4 ships with a new type of storage specially designed for large binary objects, as images or other files. Here you can learn how to use this feature for new content types and how to and prepare your already existing content types to use the new BLOB storage.

Using plone.app.blob for new content types

Just use plone.app.field.BlobField or plone.app.field.ImageField instead of atapi.FileField or atapi.ImageField (respectively) in your schema:

from Products.Archetypes import atapi 
from plone.app.blob.field import BlobField, ImageField

schema = atapi.Schema((
        BlobField('afile',
                  widget=atapi.FileWidget(label='A file',
                                          description='Some file'),
                  required=True,
                  ),
        ImageField('animage',
                  widget=atapi.ImageWidget(label='An image',
                                          description='Some image'),
                  ),
        ))

Check the Archetypes Fields Reference for details.

Preparing already existing content types

In order to prepare your own content types to use blobs and provide migration facilities to your users once plone.app.blob is available, you need to perform the following steps. Check example.blobattype for example code.

Use a schema extender to replace the FileField(s) of your content type with BlobField(s). For detailed information on how to do so please look into the archetypes.schemaextender documentation. In essence this breaks down to:

  • Creating an extension field:

    class ExtensionBlobField(ExtensionField, BlobField):
    """ derivative of blobfield for extending schemas """
  • Extending your content type to use the blob fields. So for instance if your content type ExampleATType has a field named file you will need to register a schema extender like the following:

    class ExampleATTypeExtender(object):
    adapts(IExampleATType)
    implements(ISchemaExtender)

    fields = [
    ExtensionBlobField('file',
    widget=atapi.FileWidget(
    label=_(u"File"),
    description=_(u"Some file"),
    ),
    required=True,
    validators=('isNonEmptyFile'),
    ),
    ]

    def __init__(self, context):
    self.context = context

    def getFields(self):
    return self.fields

    If you want to be able to still use your content type without plone.app.blob in sites that have not yet installed support for blobs, you will find it convenient to register the adapter conditionally like so:

    <adapter
    zcml:condition="installed plone.app.blob"
    factory=".extender.ExampleATTypeExtender" />

    This way, if plone.app.blob is not installed your original FileField(s) will be used.

  • Provide a migration function for your content. The easiest way to do so is to use the helper method from plone.app.blob. Given a portal type name it will automatically find all blob-aware fields as defined by the schema extender above and perform migrations for those. It is as simple as:

    from plone.app.blob.migrations import migrate
    def migrateExampleATTypes(context):
    return migrate(context, 'ExampleATType')

    You can now call migrateExampleATTypes from a view or a script to migrate existing content items of the specified type. If you need more control, you can write your own migrator. Please refer to example.blobattype for more details on how to do this.