Ionic 4 with Capacitor: Load local file as image source on iOS

Hey all, we’re trying to build in an offline mode into our application. A part of that requires storing images in the local filesystem so we can retrieve and display them offline. We’ve been using ImgCache.js (https://github.com/chrisben/imgcache.js/) since before the switch to Capacitor (we were previously just using Cordova), and that still works on Android, however it doesn’t display the images on iOS.

The images are hosted on AWS’ S3. My current attempt has been to use the native http Cordova plugin to retrieve the image data and then try to store that with the cordova File plugin. I’m currently grabbing the file path using the cordova File plugin’s “resolveLocalFilesystemUrl” method with Capacitor’s “convertFileSrc” method to get a file path that starts with the capacitor URL scheme. When assigning the image src to that url, nothing shows up and there are no errors or warnings.

I’ve tried a few different approaches to this, all with no avail:

  • Using the local filesystem URL (file:///path/to/file), which results in an “unable to read resource” error (makes sense)
  • Using the Capacitor Filesystem plugin to read and write, but I don’t know if there’s an issue with trying to convert the image data that gets returned from S3 to a string that something goes wrong (since it doesn’t support writing blobs)
  • Using the local filesystem URL without the file:// part (so the URL becomes /path/to/file), this results in a “file does not exist” error (though it does exist)
  • Read the data as Base64/DataURI. There’s an existing issue with a conflict between the cordova-file plugin and the HTML5 FileReader that seems to stop this from firing the onloadend event. I found a workaround for that, but then the data that comes back seems to be somewhat truncated (there isn’t enough data that comes back to be a valid Base64 string for an image of 12KB)
  • Changing where the files get stored. Currently, I’m storing them in the cordova.file.tempDirectory (I’ve also tried dataDirectory, documentsDirectory, cacheDirectory)

Thank you all for taking the time to read through this, any help/suggestions are greatly appreciated! I’ve spent way too much time trying to get this to work.

Here’s the output from running “ionic info”:

Ionic:

   Ionic CLI                     : 5.2.5
   Ionic Framework               : @ionic/angular 4.4.0
   @angular-devkit/build-angular : 0.13.9
   @angular-devkit/schematics    : 7.3.9
   @angular/cli                  : 7.3.9
   @ionic/angular-toolkit        : 1.5.1

Capacitor:

   Capacitor CLI   : 1.2.1
   @capacitor/core : 1.2.1

Cordova:

   Cordova CLI       : 7.1.0
   Cordova Platforms : ios 5.0.1
   Cordova Plugins   : cordova-plugin-ionic 5.4.5, (and 16 other plugins)

Utility:

   cordova-res : 0.6.0 (update available: 0.8.1)
   native-run  : 0.2.8 (update available: 0.2.9)

System:

   ios-deploy : 1.9.4
   ios-sim    : 8.0.1
   NodeJS     : v12.6.0
   npm        : 6.9.0
   OS         : macOS Mojave
   Xcode      : Xcode 11.1 Build version 11A1027

Here’s the output from running “cordova plugins list”:

com-sarriaroman-photoviewer 1.2.2 "PhotoViewer"
cordova-plugin-advanced-http 2.2.0 "Advanced HTTP plugin"
cordova-plugin-app-version 0.1.9 "AppVersion"
cordova-plugin-camera 4.1.0 "Camera"
cordova-plugin-cocoapod-supportx 1.6.1 "Cordova CocoaPods Dependency Support"
cordova-plugin-device 2.0.2 "Device"
cordova-plugin-document-viewer 0.9.11 "SitewaertsDocumentViewer"
cordova-plugin-downloadmanager 0.0.1 "DownloadManager"
cordova-plugin-enable-multidex 0.2.0 "Enable Multidex"
cordova-plugin-file 6.0.1 "File"
cordova-plugin-file-transfer 1.7.1 "File Transfer"
cordova-plugin-firebase-dynamiclinks 3.0.0 "FirebaseDynamicLinksPlugin"
cordova-plugin-inappbrowser 3.1.0 "InAppBrowser"
cordova-plugin-ionic 5.4.5 "cordova-plugin-ionic"
cordova-plugin-mauron85-background-geolocation 3.0.6 "CDVBackgroundGeolocation"
cordova-plugin-network-information 2.0.3-dev "Network Information"
cordova-plugin-screen-orientation 3.0.2 "Screen Orientation"
cordova-sqlite-storage 3.4.0 "Cordova sqlite storage plugin - cordova-sqlite-storage plugin version"

Hello, I was facing a similar issue regarding iOS. I managed to found a legit solution, tho the context wasn’t the same it is very similar and I also when though the same struggles. Can you give me an example of the url you are passing to resolveLocalFileSystemURL and try tweek my solution?

Alex

Hey terranmarine,

Thanks for the reply! With my latest attempt, here is the path that I’m passing to resolveLocalFIleSystemURL is:
file:///private/var/mobile/Containers/Data/Application/2139C479-DBAC-4756-8672-6A8DE686F566/tmp/720970f5-7145-4edd-9043-a3147a372246.jpg1234567891
And this is what I get back after it gets resolved: file:///var/mobile/Containers/Data/Application/2139C479-DBAC-4756-8672-6A8DE686F566/tmp/720970f5-7145-4edd-9043-a3147a372246.jpg1234567891

Hello,

This is a sample url that I pass to Plugins.Filesystem.readFile() :
file:///var/mobile/Containers/Data/Application/EFA59217-12A6-4671-B600-3A1DFFC0B46A/tmp/59549929889__B91B834F-A6F6-41FC-AACC-5C9CCFA6C069.MOV

From what I see they have the same structure, so this means that you should be able to read the file as base64 encoded string.

From here you can display the image as you pass this string to the src attribute.

If you want to have the image as a an instance of blob you can decode the string locally. It shouldn’t go to hard on the memory if you decode them one by one. Its a long process but is a working one.

Alex.