Blobs

      +

      Description — Couchbase Lite database data model concepts - blobs
      Related Content — Databases | Documents | Indexing |

      Introduction

      Couchbase Lite for JavaScript uses blobs to store the contents of images, other media files and similar format files as binary objects.

      The blob itself is not stored in the document. It is held in a separate content-addressable store indexed from the document and retrieved only on-demand.

      When a document is synchronized, the Couchbase Lite replicator adds an _attachments dictionary to the document’s properties if it contains a blob.

      Blob Objects

      The blob as an object appears in a document as a dictionary property.

      Other properties include length (the length in bytes), and optionally contentType (typically, its MIME type).

      The blob’s data (an image, audio or video content) is not stored in the document, but in a separate content-addressable store, indexed by the digest property — see Using Blobs.

      Constraints

      • Couchbase Lite
        Blobs can be arbitrarily large. They are only read on demand, not when you load the document.

      • Sync Gateway
        The maximum content size is 20 MB per blob. If a document’s blob is over 20 MB, the document will be replicated but not the blob.

      Using Blobs

      The Blob class in Couchbase Lite JavaScript provides methods to work with binary data. You can create blobs from various sources including File objects, ArrayBuffers, or URLs.

      The code in Example 1 shows how you might add a blob to a document and save it to the database. Here we use avatar as the property key and an image file as the blob data.

      Example 1. Working with blobs
      // Create the blob from a File object
      const fileInput = document.getElementById('avatarFile') as HTMLInputElement;
      if (!fileInput?.files || fileInput.files.length === 0) {
          throw new Error('Please choose an image file first.');
      }
      const file = fileInput.files[0];
      const buffer = new Uint8Array(await file.arrayBuffer());
      const blob = new NewBlob(buffer, 'image/jpeg'); (1)
      
      // Add the blob to a document
      const user: CBLDictionary = {
          type: 'user',
          username: 'jane',
          email: 'jane@email.com',
          role: 'engineer',
          avatar: blob
      };
      
      // Create a document and save
      const users = database.getCollection('users');
      const doc = users.createDocument(DocID("profile1"), user);
      const saved = await users.save(doc);
      1 Here we prepare a document to use for the example
      2 Create the blob from a File object (from a file input or drag-and-drop).
      Here we set image/jpeg as the blob MIME type.
      3 Add the blob to a document, using avatar as the property key
      Saving the document generates a random access key for each blob stored in digest, a SHA-1 encrypted property — see: [img-blob].
      We can use the avatar key to retrieve the blob object later. Note, this is the identity of the blob assigned by us; the replication auto-generates a blob for attachments and assigns its own name to it (for example, blob_1) — see [img-blob]. The digest key will be the same as generated when we saved the blob document.

      Creating Blobs

      You can create blobs from different sources in the browser:

      From File Input

      Example 2. Create blob from file input
      const fileInput = document.getElementById('avatarFile') as HTMLInputElement;
      if (!fileInput?.files || fileInput.files.length === 0) {
          throw new Error('Please choose an image file first.');
      }
      const file = fileInput.files[0];
      const buffer = new Uint8Array(await file.arrayBuffer());
      const blob = new NewBlob(buffer, 'image/jpeg');

      From Fetch API

      Example 3. Create blob from fetched data
      const response = await fetch('https://couchbase-example.com/images/avatar.jpg');
      if (!response.ok) {
          throw new Error(`Failed to fetch image: ${response.status}`);
      }
      
      // Convert the response into binary data
      const data = await response.arrayBuffer();
      
      // Create a blob from the downloaded data
      const buffer = new Uint8Array(await response.arrayBuffer());
      const blob = new NewBlob(buffer, 'image/jpeg');

      Retrieving Blobs

      Once a blob is saved in a document, you can retrieve it and access its content.

      Example 4. Retrieve and use blob
      const users = database.getCollection('users');
      const doc = await users.getDocument(DocID("profile1"));
      if (doc) {
          // Note: Import as { Blob as CBLBlob } from ‘@couchbase/lite-js’ to
          // avoid conflict with the standard Blob type.
          const blob = doc.avatar as CBLBlob;
          if (blob instanceof CBLBlob) {
              const contentType = blob.content_type ?? "None";
              const length = blob.length ?? 0;
              const digest = blob.digest;
              console.log(`Blob info:
                  Content-Type: ${contentType}
                  Length: ${length} bytes
                  Digest: ${digest}`
              );
              const content = await blob.getContents();
              // Use content as needed
          }
      } else {
          console.log('User not found');
      }

      Blob Properties

      Blob objects have several properties that provide information about the binary data:

      • contentType - The MIME type of the blob (e.g., "image/jpeg", "video/mp4")

      • length - The size of the blob in bytes

      • digest - The SHA-1 hash of the content, used for content-addressable storage

      • properties - Additional metadata stored with the blob

      Example 5. Access blob properties
      const contentType = blob.content_type ?? "None";
      const length = blob.length ?? 0;
      const digest = blob.digest;
      console.log(`Blob info:
          Content-Type: ${contentType}
          Length: ${length} bytes
          Digest: ${digest}`
      );

      TypeScript Support

      When using TypeScript, you can define document interfaces that include blob properties:

      Example 6. Type-safe blobs
      // Note: Import as { Blob as CBLBlob } from ‘@couchbase/lite-js’
      // to avoid conflict with the standard Blob type.
      interface User {
          type: 'user';
          username: string;
          email: string;
          role: string;
          avatar: CBLBlob | null;
      }
      
      const users = database.collections.users;
      const doc = await users.getDocument(DocID("profile1"));
      if (doc) {
          const blob = doc.avatar
          if (blob) {
              const content = await blob.getContents();
              // Use content as needed
          }
      }

      Syncing

      When a document containing a blob object is synchronized, the Couchbase Lite replicator generates an _attachments dictionary with an auto-generated name for each blob attachment. This is different to the avatar key and is used internally to access the blob content.

      Blob Metadata

      Blobs in Couchbase Lite follow a specific metadata structure that allows the system to identify and retrieve binary content:

      Blob metadata structure
      {
        "@type": "blob",
        "content_type": "image/jpeg",
        "length": 45678,
        "digest": "sha1-s1KdHLHCQqn/34fFxZqQRMHrQGk="
      }

      The @type property identifies this object as a blob rather than a regular nested object. The replicator uses this metadata to handle blob synchronization separately from document data.