Image data type in schema [RN Realm]

Hello, I have a similar if not identical use case as the WILDAID o-fish project. I read all related topics and posts here in the forums, but could not find my answer. I am new to S3 as well. The task is to use device sync to sync an image (<1MB) to Atlas and after that upload it to S3 and delete the image data from Atlas, just keep an url reference to the S3 object. All of this uses Triggers and Functions. I am using React Native (Expo) with flexible sync and my question is: what is the appropriate data type for the image data and how to define it in my realm schema? Should I be using the 'string' data type and encoding the image as a base64 string? Or should I be using the binary data type of some sort, perhaps 'data'? I guess it all depends on what is more efficient and what is used to store the image on S3. I don’t know what is a good practice for storing images on S3.

export class Photo extends Realm.Object<Photo> {
    photo_name!: string;
    photo!: ArrayBuffer;
    photo_url!: string;

    static schema: Realm.ObjectSchema = {
        name: "Photo",
        embedded: true,
        properties: {
            photo_name: "string",
            photo: { type: "data", optional: true, default: null },
            photo_url: "string",
        },
    };
}
export class Photo extends Realm.Object<Photo> {
    photo_name!: string;
    photo!: ArrayBuffer;
    photo_url!: string;

    static schema: Realm.ObjectSchema = {
        name: "Photo",
        embedded: true,
        properties: {
            photo_name: "string",
            photo: { type: "data", optional: true, default: null },
            photo_url: "string",
        },
    };
}

These are what I imagine the schema could look like. Also for string data types, when I wan to delete the data, do I set it o null or to ""?

Hi Damien

I would recommend that you upload to S3 directly, and only ever store the url in Realm.

If you want to trampoline on Atlas for the sake of authentication, then use a Atlas AppServices Function, but never store the actual blob in Realm, pass the image directly to that function.

Br, Kasper

I have considered that and still am, but my app is offline first with probably upwards of 70% off-the-grid usage. I would like to attempt what I see so many have done here in the forums - to compress the image down to ~100kb, sync it, and upon insertion delete and upload to S3. If not even for the image itself I would like to be able to store very very small thumbnails in Atlas.

Well, to answer your original question base64 will encode 3 bytes in 4, so that is obviously less efficient than using the binary data type directly. It will also require encoding and decoding.

I would still recommend not storing large blobs directly in Realm, but you could argue that 100KiB is not that large.

An approach to consider is to keep a queue of unsent images that you will post, once the app is online. You could use a local realm to keep track of this queue.

In this case, could you confirm if this is the correct way of using blobs:

export class Photo extends Realm.Object<Photo> {
    photo_name!: string;
    photo!: ArrayBuffer;
    photo_url!: string;

    static schema: Realm.ObjectSchema = {
        name: "Photo",
        embedded: true,
        properties: {
            photo_name: "string",
            photo: { type: "data", optional: true, default: null },
            photo_url: "string",
        },
    };
}

As for your recommendation: my initial thought was that it would add complexity to the app, but it does sound alluring. Could you expand a bit more on how I can do that? Keep a local realm collection of photos, and have some boolean field imageIsUploaded? Most importantly what method should I use to detect internet access without any headaches regarding its stability and without needed action from the user?

I’m really not familiar with the realm-js SDK (or js for that matter - I’m a developer on dart SDK) to answer with certainty, but it does look reasonable to the untrained eye.

You could listen for connection changes on the session of the synced realm and picky back of that to know when to upload. Remember transactions cannot span multiple realms, so order your code accordingly.

@Kasper_Nielsen1 , look what I found: Blob in React Native / Realm

@Andrew_Meyer , sorry for the tag, but could you please shed some light on this topic?

I didn’t know about that - as I said I’m a little outside my turf here. But you can (as described in the linked issue) use a base64 encoded string instead.

@Damian_Danev I tried this a while back when preparing an application for a presentation. I ended up hitting limitation with React Native’s implementation of Blob. There are portions of their implementation that makes it impossible to instantiate a blob from an Array Buffer. For reference, see: react-native/Blob.js at f8d8764e8f236e8495e7e5747bfe95162f3a165a · facebook/react-native · GitHub

I created the issue to track this limitation.