-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Bug Report
Plugin(s)
@capacitor/filesystem: 4.1.4
Capacitor Version
4x
Platform(s)
androidweb
Bug
Looking through the source code I discovered inconsistent behaviors between android and web:
-
androidis working great:readFile:- when
encoding = undefinedit will forcibly read the file withbase64https://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java#L29 - when
encoding = Encodingit will be read as normal string https://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java#L27
- when
writeFIle:- when
encoding = undefinedinputdatadata is decoded and saved asbinhttps://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java#L46 - when
encoding = EncodingInput data is accepted as a stringtext/plainhttps://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/android/src/main/java/com/capacitorjs/plugins/filesystem/Filesystem.java#L38
- when
-
androidhas very obvious behaviors likewebdoes not:readFile:- when
encoding = undefinedit is read and returns what is inIndexedDBhttps://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/src/web.ts#L165 - when
encoding = Encodingit is read and returns what is inIndexedDBhttps://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/src/web.ts#L165
- when
writeFile:- when
encoding = undefinedit is check isbase64and save raw toIndexedDBhttps://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/src/web.ts#L200 - when
encoding = Encodingit is check isbase64and save raw toIndexedDBhttps://github.com/ionic-team/capacitor-plugins/blob/main/filesystem/src/web.ts#L200
- when
the problem is that these actions lead to an unclear status on the web
I run on web:
await Filesystem.writeFile({
path: "test.txt",
directory: Directory.External,
data: "ASuZAADVfA==",
encoding: Encoding.UTF8
})
await Filesystem.writeFile({
path: "test.bin",
directory: Directory.External,
data: "ASuZAADVfA=="
})sha256('test.txt') === sha256('test.bin') while they are obviously two completely different files text.txt contains a base64 string and text.bin contains a data represented by base64
this behavior becomes even more weird in readFile when I run this code:
await Filesystem.writeFile({
path: "test.txt",
directory: Directory.External,
data: "hello world",
encoding: Encoding.UTF8
})
const base64 = await Filesystem.readFile({
path: "test.txt",
directory: Directory.External,
}).then(res => res.data)
console.log(base64) // "hello world" this result doesn't make sense because apparently base64.encode('hello world') is aGVsbG8gd29ybGQ=
Solution
(here is my workaround)
Encode all to base64 before saving to IndexedDB
This prevents a binary file with base64 of x from looking exactly like a text file containing utf8 of x
Make base64 explicit by saving files with encoding = undefined as ArrayBuffer or Uint8Array
Make base64 explicit by saving files with encoding = undefined as ArrayBuffer or Uint8Array into IndexedDB (this is allowed and a standard of IndexedDB)
then we will have an implementation that looks like this:
function writeFile(options: WriteFileOptions) {
if (options.encoding) {
// normal save
} else {
const data = base64ToUint8(options.data)
// normal save
}
}
function readFile(options: ReadFileOptions) {
if (options.encoding) {
// normal read
} else {
const data = ... // normal read
return uint8ToBase64(data)
}
}