Upgrading from Capacitor 2 in 2024 - Part 2: Files
Published: 2024-04-17 09:06:07

---
title: Upgrading from Capacitor 2 in 2024 - Part 2: Files
published: true
description: Updating the Files plugins
tags: 
cover_image: https://s3.eu-central-1.amazonaws.com/reconcept-dev.to-assets/capacitor/Part+2.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-03-27 15:01 +0000
---

Finally, we could start with upgrading the plugins from Cordova to Capacitor.

The first plugins we chose to upgrade all had to do with handling files. In the application you can attach files to your portfolio, which of course can be chosen from the device.

We had several plugins to manage this in Cordova, even specific ones for Android and iOS:
- @ionic-native/file-chooser (android)
- @ionic-native/file-picker (iOS)
- @ionic-native/image-picker (for iOS & android)

In Capacitor, these were all replaced using Capacitors’ `Filesystem` plugin. This plugin had all the features we needed, and works basically the same, by returning a path to where the file was located on the devices.

## Troubles ahead
The trouble began when we wanted to upload the selected file to our back-end, to connect them to the portfolio. We use S3 as storage, and have written code that uses the JavaScript `File` interface to upload the file. But the plugins all return a string to the file on the device, not the actual file itself.

We had a different Cordova plugin to handle this `@ionic-native/file`, that added a function called `resolveLocalFileSystemURL`. This returns a JavaScript `File` from the given path, which we used in our code to upload.

Here again, Capacitors’ `Filesystem` came to the rescue. The `readFile` function returns a base64 encoded string from the file contents. Then using some ‘[inspiration](https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript)’ from stack overflow, we created a `Blob` from which we can create the `File` instance we need for our existing code.

This all made sense in theory, but when executing the code we found that the contents of the file were always empty. 
We went deep into the plugin’s code to see what was going on, and we saw that the `readFile` function _uses the `FileReader` from the browser the app is running in_ But because the Capacitor plugins run outside of the Angular zone, we’d get a different instance for this `FileReader` than the one we get from ZoneJS to upload the file to the S3 storage!.

# Patching FileReader
We found [some help on the internet](https://github.com/ionic-team/Capacitor/issues/1564#issuecomment-1006942075), and now we patch the `FileReader` constructor to always use the instance used by ZoneJS (if present). Lovely stuff.
The last plugins concerning files were the `FileOpener` and `PhotoViewer`.

The `FileOpener` requests the OS for an app to open the file, and we found that the plugin from the Capacitor community `@Capacitor-community/file-opener` was a near drop-in replacement for the Cordova version. 
For the photo viewer, we also chose a community plugin: `@Capacitor-community/photoviewer`. This one actually had quite a few installation steps, because the plugin is written in Kotlin, but the steps were clear to follow and the plugin worked immediately.

The upgrading of the file handling in the app had some up’s and downs. Some plugins were easily replaced, but the whole `FileReader` issue caused a lot of headaches. Some luck was needed to realise the problem with the multiple instances, but the fix/hack works like a dream/nightmare.


If all plugins cause problems like this, we might have a bumpier road ahead of us then we’d like.