Search code examples
imagefluttercachingbase64

Cache base64 images locally in Flutter


I have the following problem with my own approach. I would like some input if there is a better way to do what I did.

In my app I get images from a source where I can not change much. There is e.g. a list of users with some info about them and an avatar. I get the data from a Rest API where the avatar is send as a bas64 string. Since base64 encoded image strings can get quite long my idea was the first time I get an image I will decode it and save it in a temporary directory using the path_provider plugin.

It looks like this right now:

Future<void> getMediaFile(int id) async {
  Directory temp = await getTemporaryDirectory();
  File imageFile = File('${temp.path}/images/${id.toString()}.jpg');

  var response = await _httpClient.getRequest(ApiPath.mediaFileById(id.toString()));
  var mediaFile = MediaFile.fromJson(response["mediafile"]);

  Uint8List decodedImage = base64Decode(mediaFile.fileContent);
  await imageFile.create(recursive: true);
  await imageFile.writeAsBytes(decodedImage);
}

And whenever I need a mediafile I will check if there already is a mediafile locally with the specific id.

Is there a better way to do this?
Is this approach not good because of any other reason?

I found a "cached_network_image" package but this can only be used if I would get the images via an url, which I can't do, because I can't change the backend in this case.


Solution

  • As with many questions like this, "it depends".

    For a small number of small (<100kb), infrequently accessed files, this is a reasonable approach. Filesystem access is usually fast enough to avoid any noticeable latency issues.

    If it's something larger that you're going to display on every page, it might be worthwhile loading the image into memory when your application starts (after saving to the local filesystem the first time).

    If it's just a 128x128 PNG avatar, I doubt it will make a difference (and all things considered, I like to keep as little in memory as possible, so in that case I'd just load from the filesystem).

    cached_network_image is only for caching images retrieved from the web, with some extra niceties to display placeholders, so that's not really relevant.