Upload image to MongoDB Atlas using Realm (offline first method)

hello,

I wanna get the user information as input in android and upload the information to MongoDB Atlas how it will be possible please send me some tutorials or docs. my question is how to store images offline in the device and then sync later to Atlas when a connection happens with the server.

Realm is not a good solution for storing blob data. Images can be very large files so leveraging a solution that can handle that type of data is recommended.

We’ve be using Firebase Storage and it works very well for that purpose.

If the images are small, like thumbnails, Realm can be used for those.

Its single user image around 100kb - 2mb . We cant upload image when user is offline .

Well, that would be true. If you are offline it would be stored locally and not uploaded. Once the connection is reestablished, it will sync automatically. Do you have some code you’ve tried that you need help with?

Did you check out the getting started guide as there’s an abundance of information about storing data in Realm. There’s also a tutorial for Getting Started With Sync you may want to take a look at after your comfortable with the basics.

I am looking for sample for image upload if you have any GitHub repo please share with me

If your image sizes are 2mb, Realm (as mentioned above) is not a good solution for image storage. If they are 100k then that would be ok but anything much larger is not recommended.

Yes i know its not solution to store image in realm but where we can store image when user is offline

Store them in files on the drive/internal storage and keep a reference to them in Realm?

How i can get on web side if i store it in mobile

For the WildAid O-FISH apps, we had this exact problem. User’s need to attach photos to boarding reports while they’re out at sea without internet connectivity.

The approach we took was to store the photo (and a thumbnail) in a Realm Object. When the device is back online, that Object gets synced to Atlas. The insert (sync) of the Photo Object into Atlas fires a database trigger, which uploads the image to S3, and replaces the image with the S3 URL. The updated Photo object is then synced back to the mobile apps - freeing up storage.

The approach is described in “Realm Data and Partitioning Strategy Behind the WildAid O-FISH Mobile Apps”

3 Likes

I am surprised that the images are stored in a Realm object/Atlas.

As mentioned in the article, storing large blob data (images) in Realm is generally discouraged for a number of reasons.

How the photos are handled is excellently covered but it’s not clear what happens if the image is > 16Mb?

Even if it’s quickly offloaded it still seems like it would be a real issue.

There is a limit to the size of a single BSON document of 16Mb, and images can easily go beyond that size limit which will lead to intermittent operation.

How do you deal with that issue?

And as a followup, as cameras get better, the image file size grows so while it may be ok on an iPhone X, when the iPhone 16x++ comes out next year with file sizes of 20Mb, what happens to the app?

1 Like

We compress the images on the device to ensure that they’re not too large

Hi @Andrew_Morgan

I implemented a similar approach but only didn’t store a public url but only tag/id of s3 upload, so I could sign a temporary url and also check access permissions for that resource on demand, might be helpful for anyone having the same use case as mine:

exports = function(fileName){
  const partition = context.user.id;
  const s3Service = context.services.get("appwise-aws").s3('us-east-1');
  
  // First check if the objet exists
  return s3Service.HeadObject({
    "Bucket": "7apps-scanned-dev",
    "Key": partition + "/" + fileName,
  }).then(() => {
      // Data shows etag, last modified, mime type etc, but we don't need those
      return s3Service.PresignURL({
         "Bucket": "7apps-scanned-dev",
         "Key": partition + "/" + fileName,
         "Method": "GET",
         "ExpirationMS": 120000,
      })
  });
  // If error happens than returned promise will catch there somewhere
};

I was hoping to reduce the size in database, because I was deleting that blob and inserting only the tag/id of s3 resource. However the sync history still keeps blob changes, so I ended up with huge history collection in __realm_sync database.

If this approach is in production, can you share some insights about how big would be the history collection?

Thanks

I got solution

  1. If you have single image you can easily store it realm as object and later you can upload it on s3 or any cloud (User compression and cropping to reduce the size of image )

  2. store image in internal storage within app folder where no one can edit or delete it store path in realm . Write a trigger where you can check if the internet is available or not if it available call the api and upload the images on the server . if images available in device you can display it