现在的indexedDB已经有几个成熟的库了,比如西面这几个,任何一个都是非常出色的。 用别人的东西好处是上手快,看文档就好,要是文档不太好,那就有点尴尬了。

dexie.js :A Minimalistic Wrapper for IndexedDB

zangodb:MongoDB-like interface for HTML5 IndexedDB

localForage:Offline storage, improved. Wraps IndexedDB, WebSQL, or localStorage using a simple but powerful AP

idb.filesystem.js: HTML5 Filesystem API polyfill using IndexedDB

File System

filer:A wrapper library for the HTML5 Filesystem API what reuses UNIX commands (cp, mv, ls) for its API.

本文的主题是基于indexedDB开发简单的文件系统,当然是简单的,可以有一个思路,觉得原来如此简单。

我也不多说了,源码在 IDBProvider.js,核心的代码反而是  _toPromise,

因为indexed的操作,基本是先创建事务,获得objectStore,再进行增删改查。

说道这里是简单版本,对目录的控制,对文件信息的控制,删除都没有具体实现,为什么呢,等你来啊。

    _toPromise(method, ...args) {
try {
return new Promise((resolve, reject) => {
// 获得事务
let trans = this.transaction
// 获得请求
let req = trans.objectStore(this._storeName)[method](...args)
// 请求成功
req.onsuccess = event => resolve(event.target.result)
// 请求失败
req.onerror = event => reject(req.error)
// 事务失败
trans.onerror = event => reject(trans.error)
})
} catch (err) {
Promise.reject(err)
}
}
let _w_ = window
_indexedDB_ = _w_.indexedDB || _w_.mozIndexedDB || _w_.webkitIndexedDB || _w_.msIndexedDB
_w_.IDBTransaction = _w_.IDBTransaction || _w_.webkitIDBTransaction || _w_.msIDBTransaction
_w_.IDBKeyRange = _w_.IDBKeyRange || _w_.webkitIDBKeyRange || _w_.msIDBKeyRange class IDBProvider { constructor() {
// DB
this._db = null
// 实例
this._instance = null
// store Name
this._storeName = IDBProvider._storeName
} get transaction() {
return this._db.transaction([this._storeName], IDBTransaction.READ_WRITE || 'readwrite')
} _toPromise(method, ...args) {
try {
return new Promise((resolve, reject) => {
// 获得事务
let trans = this.transaction
// 获得请求
let req = trans.objectStore(this._storeName)[method](...args)
// 请求成功
req.onsuccess = event => resolve(event.target.result)
// 请求失败
req.onerror = event => reject(req.error)
// 事务失败
trans.onerror = event => reject(trans.error)
})
} catch (err) {
Promise.reject(err)
}
} static getInstance(dbVersion = 1.0) {
if (this._instance) {
Promise.resolve(this._instance)
}
return new Promise((resolve, reject) => {
let request = _indexedDB_.open(IDBProvider._dbName, dbVersion)
request.onerror = event => {
return reject(null)
}
request.onsuccess = event => {
let db = request.result
// 老版本,新版本是onupgradeneeded
if (db.setVersion && db.version !== dbVersion) {
var setVersion = db.setVersion(dbVersion);
setVersion.onsuccess = function () {
db.createObjectStore(this._storeName)
this._instance = new IDBProvider()
this._instance._db = request.result
return resolve(this._instance)
}
} else {
this._instance = new IDBProvider()
this._instance._db = request.result
return resolve(this._instance)
}
}
request.onupgradeneeded = event => {
event.target.result.createObjectStore(this._storeName)
}
})
} /**
* 获取文件
* @param {*String} path
*/
getFile(path) {
return this._toPromise('get', path)
} /**
* 写入文件
* @param {*String} path 路径
* @param {*String|Blob} content 内容
* @param {*String} type
* @param {*String} append 暂无用
*/
async writeToFile(path, content, type = null, append = false) {
let data = content
// 不是blob,转为blob
if (content instanceof ArrayBuffer) {
data = new Blob([new Uint8Array(content)], { type })
} else if (typeof content === 'string') {
data = new Blob([content], { type: 'text/plain' })
} else {
data = new Blob([content])
}
await this._toPromise('put', data, path)
return this.getFile(path) /*
return new Promise((resolve, reject) => {
let data = content
// 不是blob,转为blob
if (content instanceof ArrayBuffer) {
data = new Blob([new Uint8Array(content)], { type })
} else if (typeof content === 'string') {
data = new Blob([content])
} // 存入数据
let trans = this.transaction
trans.objectStore(this._storeName).put(data, path) trans.objectStore(this._storeName).get(path).onsuccess = event => {
resolve(event.target.result)
} trans.onerror = event => {
reject(trans.error)
}
}) */
} readEntries(path = '') {
if (!path) {
return this.readAllEntries()
}
return this._toPromise('getAllKeys', IDBKeyRange.lowerBound(path)).then(r => r.filter(p => {
// 以当前路径开头 && (截断当前为空字符串,或者截断后以/开头)
return p.indexOf(path) === && (p.substring(path.length) === '' || p.substring(path.length).indexOf('/') === )
}))
} readAllEntries() {
return this._toPromise('getAllKeys')
} ensureDirectory(directory = '') {
return Promise.resolve(directory)
} clear() {
return this._toPromise('clear').then(r => true)
} /**
* 加工处理path,比如特殊字符,比如以/开头等等
* @param {*String} path
*/
_handlePath(path) {
return path
}
} IDBProvider._dbName = '_fs_db_'
IDBProvider._storeName = '_fs_store' // 测试语句
// 读取某个目录的子目录和文件: IDBProvider.getInstance().then(fs=>fs.readEntries()).then(f=>console.log(f))
// 写文件 IDBProvider.getInstance().then(fs=>fs.writeToFile('music/txt.txt','爱死你')).then(f=>console.log(f))
// 获取文件: IDBProvider.getInstance().then(fs=>fs.getFile('music/txt.txt')).then(f=>console.log(f))
// 递归创建目录: IDBProvider.getInstance().then(fs=>fs.ensureDirectory('music/vbox')).then(r=>console.log( r))
// 递归获取: IDBProvider.getInstance().then(fs=>fs.readAllEntries()).then(f=>console.log(f))
// 删除所有: IDBProvider.getInstance().then(fs=>fs.clear()).then(f=>console.log(f)).catch(err=>console.log(err))

引用:

Indexed Database API

Indexed DB API

使用 IndexedDB

Basic concepts - Web APIs | MDN

Storing images and files in IndexedDB

IndexedDB 开发指南

基于IndexedDB实现简单文件系统的更多相关文章

  1. 基于modelsim-SE的简单仿真流程—下

    基于modelsim-SE的简单仿真流程—下 编译 在 WorkSpace 窗口的 counter_tst.v上点击右键,如果选择Compile selected 则编译选中的文件,Compile A ...

  2. 基于modelsim-SE的简单仿真流程—上

    基于modelsim-SE的简单仿真流程 编写RTL功能代码 要进行功能仿真,首先得用需要仿真的模块,也就是RTL功能代码,简称待测试的模块,该模块也就是在设计下载到FPGA的电路.一个电路模块想要有 ...

  3. [置顶] 使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

    [Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier 红孩儿Cocos2d-X学习园地QQ3群:205100149,47 ...

  4. .NetCore WebApi——基于JWT的简单身份认证与授权(Swagger)

    上接:.NetCore WebApi——Swagger简单配置 任何项目都有权限这一关键部分.比如我们有许多接口.有的接口允许任何人访问,另有一些接口需要认证身份之后才可以访问:以保证重要数据不会泄露 ...

  5. TOTP 介绍及基于C#的简单实现

    TOTP 介绍及基于C#的简单实现 Intro TOTP 是基于时间的一次性密码生成算法,它由 RFC 6238 定义.和基于事件的一次性密码生成算法不同 HOTP,TOTP 是基于时间的,它和 HO ...

  6. 一款基于css3的简单的鼠标悬停按钮

    今天给大家分享一款基于css3的简单的鼠标悬停按钮.这款悬停按钮鼠标经过前边框是间断的.当鼠标经过的时候边框间隔消失.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div ...

  7. R语言实战实现基于用户的简单的推荐系统(数量较少)

    R语言实战实现基于用户的简单的推荐系统(数量较少) a<-c(1,1,1,1,2,2,2,2,3,3,3,4,4,4,5,5,5,5,6,6,7,7) b<-c(1,2,3,4,2,3,4 ...

  8. Websocket - Websocket原理(握手、解密、加密)、基于Python实现简单示例

    一.Websocket原理(握手.解密.加密) WebSocket协议是基于TCP的一种新的协议.WebSocket最初在HTML5规范中被引用为TCP连接,作为基于TCP的套接字API的占位符.它实 ...

  9. 基于RxJava2+Retrofit2简单易用的网络请求实现

    代码地址如下:http://www.demodashi.com/demo/13473.html 简介 基于RxJava2+Retrofit2实现简单易用的网络请求,结合android平台特性的网络封装 ...

随机推荐

  1. Python爬虫(九)_非结构化数据与结构化数据

    爬虫的一个重要步骤就是页面解析与数据提取.更多内容请参考:Python学习指南 页面解析与数据提取 实际上爬虫一共就四个主要步骤: 定(要知道你准备在哪个范围或者网站去搜索) 爬(将所有的网站的内容全 ...

  2. 数据结构--二叉查找树的java实现

    上代码: package com.itany.erchachazhaoshu; public class BinarySearchTree<T extends Comparable<? s ...

  3. Android DVM

    1.DVM(Dalvik Virtual Machine)概述 是Google公司自己设计用于Android平台的Java虚拟机 支持已经转化为.dex(及Dalvik Excutable)格式的Ja ...

  4. 码农的奋斗之路 CTO说 读后感

    拜读了各位大神的分享,对CTO的职责有了进一步的认识. 什么是CTO? CTO需要具备哪些技能? CTO与管理 CTO的作用是什么? 如何体现CTO的价值? CTO撸不撸代码? 小结

  5. 九、 Spring Boot 拦截器

    过滤器属于Servlet范畴的API,与spring 没什么关系. Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截 ...

  6. 系统自带vim命令学习教程

    [环境] [干货分享] vim或者vi命令在很多linux环境中自带一款学习教程,其教程说明语言还是随系统变化. 输入vimtutor这个命令会打开一款学习神器. 打开之后显示如下,vimtutor一 ...

  7. IdentityServer(12)- 使用 ASP.NET Core Identity

    IdentityServer具有非常好的扩展性,其中用户及其数据(包括密码)部分你可以使用任何想要的数据库进行持久化. 如果需要一个新的用户数据库,那么ASP.NET Core Identity是你的 ...

  8. Python爬虫(二十三)_selenium案例:动态模拟页面点击

    本篇主要介绍使用selenium模拟点击下一页,更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import unittest from selenium impor ...

  9. MyBatis_查询缓存01

    一.查询缓存 查询缓存的使用,主要是为了提高查询访问速度.将用户对同一数据的重复查询过程简单化,不在每次均从数据库中查询获取结果数据,从而提高访问速度. MyBatis的查询缓存机制,根据缓存区的作用 ...

  10. css经典布局—stick footer布局

    html部分 <div id="wrap"> <div id="main" class="clearfix"> &l ...