Quasar(Cordova)应用本地存储Base64图片方案咨询
可行方案建议
1. 使用Cordova File插件存储二进制文件(首选)
Base64比原二进制体积大30%左右,先把Base64转成Blob/ArrayBuffer,再写入到Cordova提供的本地文件系统,能大幅节省存储空间,且文件系统的容量限制远高于localStorage。
步骤:
- 安装Cordova File插件:
cordova plugin add cordova-plugin-file - 转换Base64为Blob并写入文件:
// 工具函数:Base64转Blob function base64ToBlob(base64Data, contentType = 'image/jpeg') { const sliceSize = 1024; const byteCharacters = atob(base64Data.split(',')[1]); const byteArrays = []; for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = new Array(slice.length); for (let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } return new Blob(byteArrays, { type: contentType }); } // 写入文件到应用沙盒目录 async function saveImageToFile(base64Str, fileName) { const blob = base64ToBlob(base64Str); // 获取应用的持久化存储目录(不同平台路径不同,Cordova会自动适配) const fileDir = await window.resolveLocalFileSystemURL(cordova.file.dataDirectory); const fileEntry = await fileDir.getFile(fileName, { create: true, exclusive: false }); const fileWriter = await fileEntry.createWriter(); return new Promise((resolve, reject) => { fileWriter.onwriteend = () => resolve(fileEntry.toURL()); fileWriter.onerror = reject; fileWriter.write(blob); }); } - 读取文件:
async function getImageFromFile(fileName) { const fileDir = await window.resolveLocalFileSystemURL(cordova.file.dataDirectory); const fileEntry = await fileDir.getFile(fileName, { create: false }); const file = await fileEntry.file(); return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); // 返回Base64格式 reader.onerror = reject; reader.readAsDataURL(file); }); } - 结构化对象存储:可以把对象转成JSON字符串,同样用File插件写入单独的JSON文件,或者结合下面的IndexedDB方案。
2. 使用IndexedDB存储Blob与结构化数据
IndexedDB是浏览器内置的NoSQL数据库,支持存储Blob类型(直接存二进制图片),单库容量通常可达GB级别,适合同时存储结构化对象和大体积图片。
简单实现示例:
// 初始化IndexedDB function initDB() { return new Promise((resolve, reject) => { const request = indexedDB.open('AppOfflineDB', 1); request.onupgradeneeded = (event) => { const db = event.target.result; // 创建存储对象的对象仓库 db.createObjectStore('appData', { keyPath: 'id' }); // 创建存储图片的对象仓库,key用文件名 db.createObjectStore('images', { keyPath: 'fileName' }); }; request.onsuccess = (event) => resolve(event.target.result); request.onerror = reject; }); } // 存储图片Blob async function saveImageToDB(fileName, blob) { const db = await initDB(); const transaction = db.transaction('images', 'readwrite'); const store = transaction.objectStore('images'); await store.put({ fileName, blob }); await transaction.complete; } // 存储结构化对象 async function saveDataToDB(data) { const db = await initDB(); const transaction = db.transaction('appData', 'readwrite'); const store = transaction.objectStore('appData'); await store.put(data); await transaction.complete; } // 读取图片 async function getImageFromDB(fileName) { const db = await initDB(); const transaction = db.transaction('images', 'readonly'); const store = transaction.objectStore('images'); const record = await store.get(fileName); return record?.blob; }
- 注意:读取Blob后可以用
URL.createObjectURL(blob)生成可直接用于<img>的URL,无需转回Base64,性能更好。
3. 混合方案:Pinia/Vuex + 文件/IndexedDB
- 把常用的结构化对象存在Pinia(内存)中,同时持久化到IndexedDB或JSON文件,保证离线可用。
- 图片单独存储到文件系统,在Pinia的对象中只保存图片的文件名/路径,需要展示时再从文件系统读取。
优缺点对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| Cordova File插件 | 容量大、存储效率高、原生支持 | 需要处理跨平台路径差异、文件操作异步 |
| IndexedDB | 支持事务、同时存对象和Blob、API统一 | 代码相对复杂、部分旧设备兼容性略差 |
| 混合方案 | 兼顾性能和易用性、内存与持久化分离 | 需要维护多部分存储逻辑 |
内容的提问来源于stack exchange,提问作者belhadj haythem
相关产品推荐
相关产品推荐

