本文详细介绍了如何利用PWA技术(IndexedDB/服务工作者/背景同步API)构建离线图片上传系统,实现断网时本地存储、联网后自动续传的功能方案与完整代码实现。
构建离线友好的图片上传系统
糟糕的网络连接不意味着糟糕的用户体验。通过PWA技术如IndexedDB、服务工作者和Background Sync API,你可以构建一个离线友好的图片上传系统,它能排队上传任务并在网络恢复时自动重试——让用户即使离线也能无忧上传。
系统设计流程
-
用户选择图片
系统首先让用户选择需要上传的图片文件。
-
本地存储至IndexedDB
系统检测网络连通性:若网络可用则直接上传;若不可用则将图片存入IndexedDB。
-
服务工作者监测网络恢复
图片存入IndexedDB后,系统持续监测网络连接状态。
-
后台同步处理待上传任务
当网络恢复时,系统自动尝试重新上传图片。
-
上传成功清理本地存储
图片成功上传后,系统自动删除IndexedDB中的副本。
核心实现代码
服务工作者注册
1
2
3
4
5
|
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(reg => console.log('Service Worker已注册', reg))
.catch(err => console.error('Service Worker注册失败', err));
}
|
网络状态检测
1
2
3
4
5
6
7
8
|
function uploadImage() {
if (navigator.onLine) {
// 直接上传图片
} else {
// 注册同步事件
// 将图片存储至IndexedDB
}
}
|
同步事件注册
1
2
3
4
5
6
7
|
async function registerSyncEvent() {
if ('SyncManager' in window) {
const registration = await navigator.serviceWorker.ready;
await registration.sync.register('uploadImages');
console.log('后台同步已注册');
}
}
|
IndexedDB操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// 打开数据库
let database;
function openDatabase() {
return new Promise((resolve, reject) => {
const request = indexedDB.open("myDatabase", 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains("images")) {
db.createObjectStore("images", { keyPath: "id" });
}
};
request.onsuccess = (event) => {
database = event.target.result;
resolve(database);
};
});
}
// 存储图片
async function storeImages(file) {
const db = await openDatabase();
const transaction = db.transaction("images", "readwrite");
const store = transaction.objectStore("images");
store.add({ id: Date.now(), image: file });
}
|
技术限制说明
-
网络检测可靠性
navigator.onLine
属性并不可靠,建议实现自定义网络检测方案(如向服务端发送ping请求)
-
浏览器兼容性
Background Sync API目前仅支持Chromium内核浏览器
-
存储时效性
Safari等浏览器对IndexedDB数据有7天自动清理策略
用户体验优化建议
- 添加上传状态Toast通知
- 实现进度条可视化
- 提供手动重试/取消按钮
- 显示网络状态指示器
通过这套方案,开发者能显著提升网络不稳定地区用户的使用体验,使Web应用具备原生应用般的离线能力。