I have recently published my Ionic 4 Angular App both as web app and as native Android app.
In the native Android app, everything works fine, except saving a downloaded file.
To download and save a file, I've always used file-saver
npm package as follows (this is a shared service that I invoke every time I have to download something, from a PDF to an image, etc...):
import { saveAs } from 'file-saver';
// ...
saveGenericFile(api: string, fileinfos: any, idFile: string): any {
let mediaType = 'application/pdf';
let fileName = '';
if (fileinfos != null) {
mediaType = fileinfos.contentType;
fileName = fileinfos.fileName;
}
const headers = this.base.commonHeader;
const url = this.baseUrl + api + '?id=' + idFile;
this.http.post(url, null, { headers, responseType: 'blob' }).subscribe(
(response) => {
// tslint:disable-next-line: prefer-const
let blob = new Blob([response], { type: mediaType });
saveAs(blob, fileName);
}, e => {
console.error(e);
this.toastsvc.generateToast('ERROR! An error occurred while saving this File, try later or contact support', 'danger');
}, () => {
/* do nothing */
}
);
}
As I said above, this code snippet works fine, but just when I have to save something from the web release.
The only online examples I was able to find were all about Cordova and/or previous/deprecated versions.
About Capacitor, I just found this documentation and from that I just found this code snippet:
import { Plugins, FilesystemDirectory, FilesystemEncoding } from '@capacitor/core';
const { Filesystem } = Plugins;
fileWrite() {
try {
Filesystem.writeFile({
path: 'secrets/text.txt',
data: "This is a test",
directory: FilesystemDirectory.Documents,
encoding: FilesystemEncoding.UTF8
});
} catch(e) {
console.error('Unable to write file', e);
}
}
But the issue is that my function above returns a blob and this one only accept a string for data.
So, is there any Capacitor-Native equivalent feature that I can use to download (and save) Blob files both when running as web-app and when running as Android native app?
UPDATE
I've also tried the following, but it's not working:
saveGenericFile(api: string, fileinfos: any, gidFile: string): any {
let mediaType = 'application/pdf';
let fileName = '';
if (fileinfos != null) {
mediaType = fileinfos.contentType;
fileName = fileinfos.fileName;
}
const headers = this.base.commonHeader;
const url = this.baseUrl + api + '?id=' + gidFile;
this.http.post(url, null, { headers, responseType: 'blob' }).subscribe(
(response) => {
if (!this.useCordovaDl) {
// tslint:disable-next-line: prefer-const
let blob = new Blob([response], { type: mediaType });
saveAs(blob, fileName);
} else {
this.blobFileWrite(fileName, response);
}
}, e => {
console.error(e);
this.toastsvc.generateToast('ERROR! An error occurred while saving this File, try later or contact support', 'danger');
}, () => {
/* do nothing */
}
);
}
blobFileWrite(filename: string, blobfile: Blob) {
const reader = new FileReader();
// This fires after the blob has been read/loaded.
reader.addEventListener('loadend', (e: any) => {
const text = e.srcElement.result;
this.fileWrite(filename, text);
});
// Start reading the blob as text.
reader.readAsText(blobfile);
}
fileWrite(filename: string, filedata: string) {
try {
Filesystem.writeFile({
path: filename,
data: filedata
// ,
// directory: FilesystemDirectory.Documents,
// encoding: FilesystemEncoding.UTF8
});
} catch (e) {
console.error('Unable to write file', e);
}
}
UPDATE #2
It looks like there's still an opened issue on GitHub about saving Blob data with Capacitor. I will look for a Cordova solution in the meanwhile. Or, I will simply disable every download button if platform is android or ios.
I will post every working Cordova Workaround down here, if I'll be able to find one
if what you want to achieve is save the file in the filesystem, you can save it with string base64 to filesystem
image = "data:image/png;base64,iVBORw0KGgo... bla bla bla"
Capacitor.Plugins.Filesystem.appendFile({
data:image,
path:"directory/image.png",
directory:"DOCUMENTS"
}).then(c=>{console.log("se escribiooo")})
its result in image in your filesystem (i just tried this code in the android emulator), just use the method appendFile instead writeFile, and base64 instead blob, if you only have the blob you just have to convert it to base64