indexedDB - 浏览器如何存储大文件

概述

浏览器本地存储到现在已经发展到第 3 代,抛开事实上已经废弃的 web SQL,这个过程为:

cookie → web storage → indexed db

web storge 包含 localStorage 和 sessionStorage,其中 sessionStorage 在浏览器关闭后将不复存在。web storage 并不适合大文件的存储,这就带来了 indexedDB (索引数据库)。下面截取一段 MDN 上关于 IndexedDB 的用途说明:

IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs.

因此,IndexedDB 很适合缓存 文件/多媒体 这一类所需存储空间较大的数据。

浏览器实现方式

  • IE: Extensible Storage Engine
  • Firefox: SQLite
  • Chrome: levelDB

浏览器支持情况

点击 caniuse 查看 IndexedDB 的浏览器支持情况。

indexedDB - 浏览器如何存储大文件_第1张图片

indexedDB 的用法

从最简单的用法开始

就像使用其他类型的数据库一样,使用 indexedDB 的第一步也是去关联它:

const request = indexedDB.open('helloDB', 1) // @params: dbName, version

第二个参数表示数据库版本号,createObjectStore 只能在数据库版本号更改时才可以调用,即只能在onupgradeneeded 中创建 objectStore。

然后需要给 request 设置成功和失败的回调:

request.onsuccess = e => {
    const db = e.target.result // db 是一个 IDBDatabase
}
request.onerror = err => {
    console.error(err)
}
request.onupgradeneeded = e => { // IDBVersionChangeEvent
    const db = e.target.result
}

版本更新时,onupgradeneeded 被调用,可在其中添加新的 objectStore:

const store = db.createObjectStore(storeName, {
    keyPath: 'id', // 相当于主键
    autoincrement: false
})
store.createIndex('index', 'filename', { unique: true })

createIndex 接收 3 个参数:索引名数据对象的属性配置对象

下面来做一个返回 Promise 的函数,它能在连接 indexedDB,并在 objectStore 不存在时创建它:

function openDB (dbName, version, storeName) {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(dbName, version)
    request.onsuccess = function (e) {
      resolve(e.target.result)
    } 
    request.onerror = function (e) {
      reject(e)
    } 
    request.onupgradeneeded = function (e) {
      const db = e.target.result
      
      if (!db.objectStoreNames.contains(storeName)) {
        const objectStore = db.createObjectStore(storeName, {
          keyPath: 'id',
          autoIncrement: true
        })
        objectStore.createIndex('index', 'filename', {
          unique: false
        })
      }
    } 
  })
} 

这样,就可以在连接数据库后往 store 里放东西了:

function doSomethingToDb (dbName, version, storeName) {
  openDB(dbName, version, storeName)
    .then(db => {
      const tx = db.transaction(storeName, 'readwrite')
      const store = tx.objectStore(storeName)
      const req = store.put({
        filename: '涡轮增压机',
        version: 102,
        author: 'John'
      })
      req.onsuccess = res => {
        console.log('保存成功', res)
      } 
    })
    .catch(err => {
      console.error(err)
    })
}   

doSomethingToDb('worldDB', 1, 'Files')

查找

通过主键查找

const req = store.get('main_key')
req.onsuccess = (res) => {
    console.log(res)
}

IndexedDB 特点

  • 一个 indexedDB 数据库只对同域名有访问权限,不同域可以有同名数据库,不冲突。
  • 在隐私模式下不可用。这与 cookie & localStorage 相同,这个特点可以用来测试不支持 IndexedDB 的情况。

资源地图

  • using-indexeddb-manage-3d-webgl-assets/

    • 与 working-with-indexeddb 互为补充
  • w3c IndexedDB(最权威的文档)

  • MDN: IndexedDB API

你可能感兴趣的:(Web前端)