闽公网安备 35020302035485号
3.上传失败和上传中断处理
classFileStorage{
private db: IDBDatabase | null = null
private dbName = 'fileStore'
private storeName = 'files'
private openCallback: () =>void
constructor(open = () => {}) {
this.openCallback = open
this.openDatabase()
}
// 堆代码 duidaima.com
// 打开或创建数据库
private openDatabase(): void {
const request = indexedDB.open(this.dbName, 1)
request.onupgradeneeded = (event) => {
this.db = (event.target as IDBOpenDBRequest).result
if (!this.db.objectStoreNames.contains(this.storeName)) {
this.db.createObjectStore(this.storeName, {
keyPath: 'id',
autoIncrement: true
})
}
}
request.onsuccess = (event) => {
this.db = (event.target as IDBOpenDBRequest).result
this.openCallback()
}
request.onerror = (event) => {
console.error('Error opening database:', event)
}
}
// 插入整个 fileList 数组
public async insertFileList(fileList: fileInfoWithId[]): Promise<void> {
const fileContents = awaitPromise.all(
fileList.map((file) =>this.readFileAsArrayBuffer(file.raw))
)
awaitthis.transaction(async (transaction) => {
const objectStore = transaction.objectStore(this.storeName)
for (let i = 0; i < fileList.length; i++) {
const file = fileList[i]
const content = fileContents[i]
awaitthis.insertObjectStore(objectStore, { ...file, content })
}
})
}
// 插入单个 fileInfo
public async insertFile(fileInfo: fileInfoWithId): Promise<void> {
this.insertFileList([fileInfo])
}
// 读取文件为 ArrayBuffer
private readFileAsArrayBuffer(file: File): Promise<ArrayBuffer> {
returnnewPromise((resolve, reject) => {
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = () => resolve(reader.result asArrayBuffer)
reader.onerror = (error) => reject(error)
})
}
// 插入对象到 objectStore
private async insertObjectStore(
objectStore: IDBObjectStore,
file: fileInfoWithId & { content: ArrayBuffer }
): Promise<void> {
returnnewPromise((resolve, reject) => {
const request = objectStore.add(file)
request.onsuccess = () => resolve()
request.onerror = (error) => reject(error)
})
}
// 根据 ID 列表删除数据
public async deleteByIds(ids: number[]): Promise<void> {
awaitthis.transaction(async (transaction) => {
const objectStore = transaction.objectStore(this.storeName)
for (const id of ids) {
const request = objectStore.delete(id)
awaitthis.waitForRequest(request)
}
})
}
// 根据单个 ID 删除数据
public async deleteById(id: number): Promise<void> {
awaitthis.transaction(async (transaction) => {
const objectStore = transaction.objectStore(this.storeName)
const exists = awaitthis.checkIfExists(objectStore, id)
if (!exists) {
console.warn(`No file found with id ${id}`)
return
}
console.log(`Deleting file with id ${id}`)
const request = objectStore.delete(id)
awaitthis.waitForRequest(request)
})
}
// 检查是否存在指定 ID 的数据
private async checkIfExists(
objectStore: IDBObjectStore,
id: number
): Promise<boolean> {
returnnewPromise((resolve) => {
const getRequest = objectStore.get(id)
getRequest.onsuccess = () => {
resolve(getRequest.result !== undefined) // 如果 result 是 undefined,说明没有找到该 ID
}
getRequest.onerror = (error) => {
console.error('Check existence error:', error)
resolve(false)
}
})
}
// 查找所有数据
public async findAll(): Promise<fileInfoWithId[]> {
returnawaitthis.transaction(async (transaction) => {
const objectStore = transaction.objectStore(this.storeName)
const request = objectStore.getAll()
returnawaitthis.waitForRequest(request)
})
}
// 清空整个对象存储中的所有数据
public async clearDatabase(): Promise<void> {
awaitthis.transaction(async (transaction) => {
const objectStore = transaction.objectStore(this.storeName)
const request = objectStore.clear()
awaitthis.waitForRequest(request)
console.log('Database cleared successfully')
})
}
// 带分页的查找功能
public async findWithPagination(
page: number,
pageSize: number
): Promise<fileInfoWithId[]> {
returnawaitthis.transaction(async (transaction) => {
const objectStore = transaction.objectStore(this.storeName)
const start = (page - 1) * pageSize
const result: fileInfoWithId[] = []
let currentIndex = 0
const cursorRequest = objectStore.openCursor()
returnnewPromise<fileInfoWithId[]>((resolve, reject) => {
cursorRequest.onerror = (error) => reject(error)
cursorRequest.onsuccess = (event) => {
const cursor = (event.target as IDBRequest).result
if (cursor) {
if (currentIndex >= start && currentIndex < start + pageSize) {
result.push(cursor.value)
}
if (currentIndex < start + pageSize) {
currentIndex++
cursor.continue()
} else {
resolve(result)
}
} else {
resolve(result)
}
}
})
})
}
// 创建事务并执行回调
private async transaction<T>(
callback: (transaction: IDBTransaction) =>Promise<T>
): Promise<T> {
returnnewPromise((resolve, reject) => {
if (!this.db) {
reject(newError('Database not initialized'))
return
}
const transaction = this.db.transaction([this.storeName], 'readwrite')
callback(transaction).then(resolve).catch(reject)
transaction.oncomplete = () => {
console.log('Transaction completed')
}
transaction.onerror = (error) => {
console.error('Transaction error:', error)
reject(error)
}
})
}
// 等待请求完成
private waitForRequest<T>(request: IDBRequest<T>): Promise<T> {
returnnewPromise((resolve, reject) => {
request.onsuccess = () => resolve(request.result)
request.onerror = (error) => {
console.error('Request error:', error)
reject(error)
}
})
}
}
exportdefault FileStorage
并发任务控制classconcurrencyControl{
private maxConcurrency: number
private queue: any[]
private running: number
private onAllTasksCompleted: Function
constructor(
maxConcurrency: number,
onAllTasksCompleted: Function = () => {}
) {
this.maxConcurrency = maxConcurrency
this.queue = []
this.running = 0
this.onAllTasksCompleted = onAllTasksCompleted
}
addQueue(queue: Function[]) {
this.queue.push(...queue)
this.run()
}
addTask(task: Function) {
this.queue.push(task)
this.run()
}
run() {
while (this.running < this.maxConcurrency && this.queue.length) {
this.running++
const task = this.queue.shift()
Promise.resolve(task()).finally(() => {
this.running--
this.run()
if (this.running === 0 && this.queue.length === 0) {
this.onAllTasksCompleted()
}
})
}
}
}
exportdefault concurrencyControl