typescript - 我如何在 Ionic4 Angular 中使用 Capacitor 保存已下載的文件?
我最近將我的 Ionic 4 Angular 應用程式同時發佈為網頁應用程式和原生 Android 應用程式。
在原生 Android 應用程式中,所有功能運作正常,除了保存已下載的檔案。
要下載並保存檔案,我一直使用 file-saver npm 套件,如下所示(這是一個共用服務,每次我需要下載某些東西時都會調用它,從 PDF 到圖片等...):
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 */
}
);
}
如我上面所說,這段程式碼運作正常,但只是當我必須從網頁釋出中保存某些東西時。
我能找到的唯一線上範例都是關於 Cordova 和/或舊版/已棄用的版本。
關於 Capacitor,我只找到這份文件,並從中找到這個程式碼片段:
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);
}
}
但問題是,我上面的函數返回的是一個二進位大物件,而這個函數只接受字串作為資料。
那麼,是否有任何 Capacitor-Native 的對應功能可以讓我在作為網頁應用程式運行以及作為 Android 原生應用程式運行時,下載(並保存)Blob 文件?
更新
我也試過以下方法,但它不起作用:
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);
}
}
更新 #2
看起來 GitHub 上仍然有關於使用 Capacitor 保存 Blob 數據的未解決問題。與此同時,我會尋找 Cordova 的解決方案。或者,如果平台是 Android 或 iOS,我將直接禁用所有下載按鈕。
如果我能找到任何有效的 Cordova 變通方法,我會在這裡貼出來
答案#1
如果你想要達到的目標是在文件系統中保存檔案,你可以將其以字串的 base64 形式保存到文件系統中
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")})
它在你的文件系統中生成圖片(我剛在安卓模擬器中試過這段程式碼),只需使用 appendFile 方法而不是 writeFile,並使用 base64 而非 blob,如果你只有 blob,你只需要將它轉換成 base64
答案#2
和你分享我的應對方法。
我正在使用 Filesystem 插件的網頁實現。不知道這是否是個好方法,但它有助於解決我的問題。
import { FilesystemDirectory, FilesystemEncoding } from '@capacitor/core'
// const { Filesystem } = Plugins // => Doesn't work with blob in native
// Workaround: Use Web-Implementation of plugin
import { FilesystemPluginWeb } from '@capacitor/core/dist/esm/web/filesystem.js'
const Filesystem = new FilesystemPluginWeb()
