indexedDB 存储 js文件 xml文件 大文件缓存 并导出使用
目錄
一. 打開數(shù)據(jù)庫
二.?在數(shù)據(jù)庫中創(chuàng)建一個對象倉庫
(1). 更新
(2). 成功
(3). 錯誤
(4). 被阻斷
三 .獲得文件數(shù)據(jù)并存儲和提取使用
(1) . 獲取文件
(2).存儲到數(shù)據(jù)庫
(3).讀取文件
起因:在網(wǎng)速慢,需要加載的文件很大(大于5M),每次刷新界面都要重新加載的情況。選擇把文件存在瀏覽器的indexedDB數(shù)據(jù)庫中,在存儲后,以后再刷新界面,從本地的數(shù)據(jù)庫中提取,就不用每次加載了。
(如果是打開本地的文件,上傳到數(shù)據(jù)庫,網(wǎng)上有很多成熟的方案)
參考文獻:http://www.ruanyifeng.com/blog/2018/07/indexeddb.html
? ? ? ? ? ? ? ? ??https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
? ? ? ? ? ? ? ? ??https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB
? ? ? ? ? ? ? ? ? 讀取文件:https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
目標:在數(shù)據(jù)庫存入2個文件 一個是js文件,主鍵就是js ; 另一個是個xml文件,主鍵就是xml
一. 打開數(shù)據(jù)庫
先定義變量
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB;
var request = indexedDB.open("opencv",1);
var db;
open這個動作,如果以前沒有這個數(shù)據(jù)庫,就會新建數(shù)據(jù)庫,
? ? ? ? ? ? ? ? ? ? ? ? ? 如果有數(shù)據(jù)庫,就打開,
? ? ? ? ? ? ? ? ? ? ? ? ? 如果有數(shù)據(jù)庫,但版本改變,就會執(zhí)行升級,? ? ? ? ? ? ? ? ? ? ? ? ?
open接受2個參數(shù),數(shù)據(jù)庫名 和 版本號,版本號可以不寫,不寫的話,第一次版本默認是1
二.?在數(shù)據(jù)庫中創(chuàng)建一個對象倉庫
?打開數(shù)據(jù)庫就像任何其他操作一樣 — 你必須進行 "request"。
open 請求不會立即打開數(shù)據(jù)庫或者開始一個事務。 對?open()?函數(shù)的調(diào)用會返回一個我們可以作為事件來處理的包含 result(成功的話)或者錯誤值的?IDBOpenDBRequest?對象。在 IndexedDB 中的大部分異步方法做的都是同樣的事情 - 返回一個包含 result 或錯誤的?IDBRequest?對象。open 函數(shù)的結(jié)果是一個?IDBDatabase?對象的實例。
返回結(jié)果有4中情況?onupgradeneeded(更新)、onsuccess(成功)、onerror(失敗)、onblocked(被阻塞)
(1). 更新
? ? ?在第一次新建數(shù)據(jù)庫時,版本不寫會默認是1,版本從無到有,也算是版本更新。
? ? 當版本改變,也會觸發(fā)更新。
? ? 在第一次新建數(shù)據(jù)庫后,第一個步驟是新建表,如果是再次更新時,就要判斷數(shù)據(jù)庫中有沒有這個表,如果沒有就新建表。
? ??① 新建表 'oc'
? ??② 如果是再次更新,表存在,就刪除表中的數(shù)據(jù)。
? ? 刪除數(shù)據(jù)的方法delete()
? ??request.onupgradeneeded = function (event) {
?? ?console.log('數(shù)據(jù)庫更新');
? ? db = event.target.result;
? ? var objectStore;
? ? if (!db.objectStoreNames.contains('oc')) {
?? ? ?console.log("新建表");
? ? ? objectStore = db.createObjectStore('oc');?? ?
? ? }else{
?? ? ?console.log("版本更新,數(shù)據(jù)刪除更新");
?? ? ?var t = event.target.transaction;
?? ? ?var requ = t.objectStore('oc').delete("js");
?? ? ?var requ2 = t.objectStore('oc').delete("xml");
?? ? ?requ.onsuccess = function (event) { console.log('數(shù)據(jù)庫表數(shù)據(jù)js刪除成功'); };
?? ? ?requ.onerror = function (event) { console.log('數(shù)據(jù)庫表數(shù)據(jù)js刪除成功'); };
?? ? ?requ2.onsuccess = function (event) { console.log('數(shù)據(jù)庫表數(shù)據(jù)xml刪除成功'); };
?? ? ?requ2.onerror = function (event) { console.log('數(shù)據(jù)庫表數(shù)據(jù)xml刪除成功'); };
? ? }?? ? ?
}
(2). 成功
在新建數(shù)據(jù)庫時,先執(zhí)行更新,再執(zhí)行成功。
在數(shù)據(jù)庫存在時,版本號不變的情況下,直接執(zhí)行成功。
檢查表里是否有js文件數(shù)據(jù)存在,如果存在,就加載把2個文件讀取出來 read(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如果不存在,就獲取2個文件getFile(),并存到數(shù)據(jù)庫中。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 如果檢測失敗,也獲取這2個文件,因為主鍵是一樣的,會覆蓋之前存的這2個文件。
讀取數(shù)據(jù)的方法get()
這里不嚴謹?shù)氖?#xff0c;如果當用戶在存儲數(shù)據(jù)時,把網(wǎng)頁關閉了,導致2個文件只有一個存儲成功了,
(這里xml是小文件,js是大文件),這時,檢測時,如果沒檢測到js文件,就會把2個文件再加載一遍,
如果不想這樣,可以,兩個文件分別判斷是否存在,分別加載。
(我直接把獲取2個文件寫在一個函數(shù)中了,你可以通過傳參,分別獲取)
request.onsuccess = function (event) {
?? ?console.log('數(shù)據(jù)庫打開成功');
?? ?db = request.result;?? ? ?
? ? db.onerror = function (event) { console.log("Error creating/accessing IndexedDB database"); };
? ? //是否有表,表里是否有那條數(shù)據(jù)
? ? var r = db.transaction(['oc']).objectStore('oc').get('js');
? ? r.onsuccess = function(event) {
? ??? ? ? var d = event.target.result;
? ? ? ?if(!d){?
? ? ?? ? ?console.log('表中無數(shù)據(jù),或數(shù)據(jù)已清空');
? ? ?? ? ?getFile();?
? ? ? ?}
? ? ? ?else{
? ? ?? ? ? console.log('加載本地保存數(shù)據(jù)');
? ? ?? ? ? read('xml');
? ? ?? ? ? read('js');
? ? ? ?}?
? ? };
? ? r.οnerrοr= function() {
? ? ?? ?console.log('查詢失敗');
? ? ?? ?getFile();
?? ?}? ??
};
(3). 錯誤
在數(shù)據(jù)庫打開失敗時,可以頁面提示打開失敗,或者在控制臺打印。
request.onerror = function (event) { console.log('數(shù)據(jù)庫打開報錯'); };
(4). 被阻斷
打印錯誤信息
request.onblocked = function() { console.log("Your database version can't be upgraded because the app is open somewhere else.");}
三 .獲得文件數(shù)據(jù)并存儲和提取使用
(1) . 獲取文件
js文件用blob類型存儲。
xml文件用arraybuffer類型存儲。
當文件加載成功,將文件存到數(shù)據(jù)庫中 putInDB( 類型,主鍵);
function getFile(){
?? ?var xhr = new XMLHttpRequest();
?? ?var xhr2 = new XMLHttpRequest();
?? ?var blob,arraybuffer;
?? ?xhr.open("GET", 根目錄+'/static/oc/oc.js', true);
?? ?xhr2.open("GET", 根目錄+'/static/oc/hd.xml', true);
?? ?xhr.responseType = "blob";
?? ?xhr2.responseType = "arraybuffer";
?? ?xhr.addEventListener("load", function () {
? ? ? ? ?if (xhr.status === 200) { ? ? ? ? ?
? ? ? ? ? ? ?blob = xhr.response; ? ? ? ? ? ? ?
? ? ? ? ? ? ?console.log('獲取opencv.js成功');
? ? ? ? ??? ? putInDB(blob,'js'); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ?}
? ? ?}, false);
?? ? xhr2.addEventListener("load", function () {
??? ??? ? if (xhr2.status === 200) {
??? ??? ??? ?console.log('獲取xml成功');
??? ??? ??? ?arraybuffer = xhr2.response;
??? ??? ??? ?putInDB(arraybuffer,'xml');?
??? ??? ? }
??? ?}, false);?? ??
? ? xhr.send(); ? ? ?? ? ?? ?
??? xhr2.send(); ? ?
}
(2).存儲到數(shù)據(jù)庫
這里用到的數(shù)據(jù)庫的事務,事務提供了三種模式:readonly、readwrite?和?versionchange?。
想要執(zhí)行寫這個操作,用readwrite。
增加一條數(shù)據(jù)時,add() 方法的調(diào)用時,對象倉庫中不能存在相同鍵的對象。
如果新加的這條數(shù)據(jù),可以覆蓋數(shù)據(jù)庫中本來存在相同鍵的,用put()方法。
寫入完,讀取數(shù)據(jù),加載使用 read()。
function putInDB(type,id) {
? ?var transaction = db.transaction(["oc"], 'readwrite');
? ?var put = transaction.objectStore('oc').put(type,id);
? ?put.onsuccess = function (event) { console.log('數(shù)據(jù)'+id+'寫入成功'); };
? ?put.onerror = function (event) { console.log('數(shù)據(jù)'+id+'寫入失敗'); }
? ?read(id);
}
(3).讀取文件
如果是使用js,可以在html或jsp頁面內(nèi)寫一個帶id的script,用于寫入。
? (想過寫入到某個空的js文件中,再在某個想執(zhí)行的時候執(zhí)行,
? ? 但瀏覽器不能讓這樣做的,如果有更好的寫入執(zhí)行,請留個言指教下 ^-^)
這里對讀取出的不同數(shù)據(jù)做處理
比如讀取js文件,用 FileReader.readAsText()方法將數(shù)據(jù)轉(zhuǎn)變成字符串。
轉(zhuǎn)變完成,寫入到script中,用jquery的html()方法寫入,就直接執(zhí)行了。
html:?<script type="text/javascript" id="oc"></script>
js:
var xmlreq;
function read(id) {
? ?var req = db.transaction(['oc']).objectStore('oc').get(id);?? ?
? ?req.onerror = function(event) { console.log('讀取'+id+'數(shù)據(jù)失敗'); };
? ?req.onsuccess = function(event) {
?? ? ? if(id=='xml'){
?? ??? ? ? xmlreq = event.target.result;
? ? ? ? ? ?let data = new Uint8Array(xmlreq);
? ? ? ? ? ?// 這里可以處理xml文件數(shù)據(jù)
?? ? ? }else{
?? ??? ? ?var file = event.target.result;
?? ??? ? ?var reader = new FileReader();
?? ??? ? ?reader.addEventListener("loadend", function() {?
?? ??? ? ? ? ? ?//處理數(shù)據(jù)?
?? ??? ? ? ? ? ?$("#oc").html(reader.result);? ? ? ? ? ? ??
?? ??? ? ?});
?? ??? ? ?reader.readAsText(file);
?? ? ? }
? ?};
}
總結(jié)
以上是生活随笔為你收集整理的indexedDB 存储 js文件 xml文件 大文件缓存 并导出使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2977 二叉堆练习1 codevs
- 下一篇: greenplum单机版初始化日志