Skip to content
Search

    Serving Media Data

    CAP provides out-of-the-box support for serving media and other binary data.

    Annotating Media Elements

    You can use the following annotations in the service model to indicate that an element in an entity contains media data.

    @Core.MediaType
    Indicates that the element contains media data (directly or using a redirect). The value of this annotation is either a string with the contained MIME type (as shown in the first example), or is a path to the element that contains the MIME type (as shown in the second example).
    @Core.IsMediaType
    Indicates that the element contains a MIME type. The @Core.MediaType annotation of another element can reference this element.
    @Core.IsURL @Core.MediaType
    Indicates that the element contains a URL pointing to the media data (redirect scenario).
    @Core.ContentDisposition.Filename
    Indicates that the element is expected to be displayed as an attachment, that is downloaded and saved locally. The value of this annotation is a path to the element that contains the Filename (as shown in the fourth example ).
    @Core.ContentDisposition.Type
    Can be used to instruct the browser to display the element inline, even if @Core.ContentDisposition.Filename is specified, by setting to inline (see the fifth example). If omitted, the behavior is @Core.ContentDisposition.Type: 'attachment'.

    @Core.ContentDisposition.Type is currently only available for the Node.js runtime.

    The following examples show these annotations in action:

    1. Media data is stored in a database with a fixed media type image/png:
    entity Books { //...
      image : LargeBinary @Core.MediaType: 'image/png';
    }
    
    1. Media data is stored in a database with a variable media type:
    entity Books { //...
      image : LargeBinary @Core.MediaType: imageType;
      imageType : String  @Core.IsMediaType;
    }
    
    1. Media data is stored in an external repository:
    entity Books { //...
      imageUrl  : String @Core.IsURL @Core.MediaType: imageType;
      imageType : String @Core.IsMediaType;
    }
    
    1. Content disposition data is stored in a database with a variable disposition:
      entity Authors { //...
        image : LargeBinary @Core.MediaType: imageType @Core.ContentDisposition.Filename: fileName;
        fileName : String;
      }
      
    2. The image shall have the suggested file name but be displayed inline nevertheless:
    entity Authors { //...
      image : LargeBinary @Core.MediaType: imageType @Core.ContentDisposition.Filename: fileName @Core.ContentDisposition.Type: 'inline';
      fileName : String;
    }
    

    Learn more about the syntax of annotations.

    In case you rename the properties holding the media type or content disposition information in a projection, you need to update the annotation’s value as well.

    Reading Media Resources

    Read media data using GET requests of the form /Entity(<ID>)/mediaProperty:

    GET ../Books(201)/image
    > Content-Type: application/octet-stream
    

    The response’s Content-Type header is typically application/octet-stream.

    Although allowed by RFC 2231, Node.js does not support line breaks in HTTP headers. Hence, make sure you remove any line breaks from your @Core.IsMediaType content.

    Read media data with @Core.ContentDisposition.Filename in the model:

    GET ../Authors(201)/image
    > Content-Disposition: 'attachment; filename="foo.jpg"'
    

    The media data is streamed automatically.

    Creating a Media Resource

    As a first step, create an entity without media data using a POST request to the entity. After creating the entity, you can insert a media property using the PUT method. The MIME type is passed in the Content-Type header. Here are some sample requests:

    POST ../Books
    Content-Type: application/json
    { <JSON> }
    
    PUT ../Books(201)/image
    Content-Type: image/png
    <MEDIA>
    

    The media data is streamed automatically.

    Updating Media Resources

    The media data for an entity can be updated using the PUT method:

    PUT ../Books(201)/image
    Content-Type: image/png
    <MEDIA>
    

    The media data is streamed automatically.

    Deleting Media Resources

    One option is to delete the complete entity, including all media data:

    DELETE ../Books(201)
    

    Alternatively, you can delete a media data element individually:

    DELETE ../Books(201)/image
    

    Using External Resources

    The following are requests and responses for the entity containing redirected media data from the third example, “Media data is stored in an external repository”.

    This format is used by OData-Version: 4.0. To be changed in OData-Version: 4.01.

    GET: ../Books(201)
    >{ ...
        image@odata.mediaReadLink: "http://other-server/image.jpeg",
        image@odata.mediaContentType: "image/jpeg",
        imageType: "image/jpeg"
    }
    

    Serving Binary Data in OData Services — Conventions and Limitations

    General Conventions

    • Binary data in payloads must be a Base64 encoded string.
    • Binary data in URLs must have the format binary'<url-safe base64 encoded>'. For example:
    $filter=ID eq binary'Q0FQIE5vZGUuanM='
    

    Node.js Runtime Conventions and Limitations

    • The usage of binary data in some advanced constructs like the $apply query option and /any() might be limited.
    • On SQLite, binary strings are stored as plain strings, whereas a buffer is stored as binary data. As a result, if in a CDS query, a binary string is used to query data stored as binary, this wouldn’t work.
    • SAP HANA Database Client for Node.js (HDB) and SAP HANA Client for Node.js (@sap/hana-client) packages handle binary data differently. For example, HDB automatically converts binary strings into binary data, whereas SAP HANA Client doesn’t.
    • In the Node.js Runtime, all binary strings are converted into binary data according to SAP HANA property types. To disable this default behavior, you can set the environment variable cds.env.hana.base64_to_buffer to false.