Open onvno opened 5 years ago
html
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<h1>IndexedDB Demo: storing blobs, e-publication example</h1>
<div class="note">
<p>
Works and tested with:
</p>
<div id="compat">
</div>
</div>
<div id="msg">
</div>
<form id="register-form">
<table>
<tbody>
<tr>
<td>
<label for="pub-title" class="required">
Title:
</label>
</td>
<td>
<input type="text" id="pub-title" name="pub-title" />
</td>
</tr>
<tr>
<td>
<label for="pub-biblioid" class="required">
Bibliographic ID:<br/>
<span class="note">(ISBN, ISSN, etc.)</span>
</label>
</td>
<td>
<input type="text" id="pub-biblioid" name="pub-biblioid"/>
</td>
</tr>
<tr>
<td>
<label for="pub-year">
Year:
</label>
</td>
<td>
<input type="number" id="pub-year" name="pub-year" />
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
<label for="pub-file">
File image:
</label>
</td>
<td>
<input type="file" id="pub-file"/>
</td>
</tr>
<tr>
<td>
<label for="pub-file-url">
Online-file image URL:<br/>
<span class="note">(same origin URL)</span>
</label>
</td>
<td>
<input type="text" id="pub-file-url" name="pub-file-url"/>
</td>
</tr>
</tbody>
</table>
<div class="button-pane">
<input type="button" id="add-button" value="Add Publication" />
<input type="reset" id="register-form-reset"/>
</div>
</form>
<form id="delete-form">
<table>
<tbody>
<tr>
<td>
<label for="pub-biblioid-to-delete">
Bibliographic ID:<br/>
<span class="note">(ISBN, ISSN, etc.)</span>
</label>
</td>
<td>
<input type="text" id="pub-biblioid-to-delete"
name="pub-biblioid-to-delete" />
</td>
</tr>
<tr>
<td>
<label for="key-to-delete">
Key:<br/>
<span class="note">(for example 1, 2, 3, etc.)</span>
</label>
</td>
<td>
<input type="text" id="key-to-delete"
name="key-to-delete" />
</td>
</tr>
</tbody>
</table>
<div class="button-pane">
<input type="button" id="delete-button" value="Delete Publication" />
<input type="button" id="clear-store-button"
value="Clear the whole store" class="destructive" />
</div>
</form>
<form id="search-form">
<div class="button-pane">
<input type="button" id="search-list-button"
value="List database content" />
</div>
</form>
<div>
<div id="pub-msg">
</div>
<div id="pub-viewer">
</div>
<ul id="pub-list">
</ul>
</div>
css
body {
font-size: 0.8em;
font-family: Sans-Serif;
}
form {
background-color: #cccccc;
border-radius: 0.3em;
display: inline-block;
margin-bottom: 0.5em;
padding: 1em;
}
table {
border-collapse: collapse;
}
input {
padding: 0.3em;
border-color: #cccccc;
border-radius: 0.3em;
}
.required:after {
content: "*";
color: red;
}
.button-pane {
margin-top: 1em;
}
#pub-viewer {
float: right;
width: 48%;
height: 20em;
border: solid #d092ff 0.1em;
}
#pub-viewer iframe {
width: 100%;
height: 100%;
}
#pub-list {
width: 46%;
background-color: #eeeeee;
border-radius: 0.3em;
}
#pub-list li {
padding-top: 0.5em;
padding-bottom: 0.5em;
padding-right: 0.5em;
}
#msg {
margin-bottom: 1em;
}
.action-success {
padding: 0.5em;
color: #00d21e;
background-color: #eeeeee;
border-radius: 0.2em;
}
.action-failure {
padding: 0.5em;
color: #ff1408;
background-color: #eeeeee;
border-radius: 0.2em;
}
.note {
font-size: smaller;
}
.destructive {
background-color: orange;
}
.destructive:hover {
background-color: #ff8000;
}
.destructive:active {
background-color: red;
}
js
(function () {
var COMPAT_ENVS = [
['Firefox', ">= 16.0"],
['Google Chrome',
">= 24.0 (you may need to get Google Chrome Canary), NO Blob storage support"]
];
var compat = $('#compat');
compat.empty();
compat.append('<ul id="compat-list"></ul>');
COMPAT_ENVS.forEach(function(val, idx, array) {
$('#compat-list').append('<li>' + val[0] + ': ' + val[1] + '</li>');
});
const DB_NAME = 'mdn-demo-indexeddb-epublications';
const DB_VERSION = 1; // Use a long long for this value (don't use a float)
const DB_STORE_NAME = 'publications';
var db;
// Used to keep track of which view is displayed to avoid uselessly reloading it
var current_view_pub_key;
function openDb() {
console.log("openDb ...");
var req = indexedDB.open(DB_NAME, DB_VERSION);
req.onsuccess = function (evt) {
// Better use "this" than "req" to get the result to avoid problems with
// garbage collection.
// db = req.result;
db = this.result;
console.log("openDb DONE");
};
req.onerror = function (evt) {
console.error("openDb:", evt.target.errorCode);
};
req.onupgradeneeded = function (evt) {
console.log("openDb.onupgradeneeded");
var store = evt.currentTarget.result.createObjectStore(
DB_STORE_NAME, { keyPath: 'id', autoIncrement: true });
store.createIndex('biblioid', 'biblioid', { unique: true });
store.createIndex('title', 'title', { unique: false });
store.createIndex('year', 'year', { unique: false });
};
}
/**
* @param {string} store_name
* @param {string} mode either "readonly" or "readwrite"
*/
function getObjectStore(store_name, mode) {
var tx = db.transaction(store_name, mode);
return tx.objectStore(store_name);
}
function clearObjectStore(store_name) {
var store = getObjectStore(DB_STORE_NAME, 'readwrite');
var req = store.clear();
req.onsuccess = function(evt) {
displayActionSuccess("Store cleared");
displayPubList(store);
};
req.onerror = function (evt) {
console.error("clearObjectStore:", evt.target.errorCode);
displayActionFailure(this.error);
};
}
function getBlob(key, store, success_callback) {
var req = store.get(key);
req.onsuccess = function(evt) {
var value = evt.target.result;
if (value)
success_callback(value.blob);
};
}
/**
* @param {IDBObjectStore=} store
*/
function displayPubList(store) {
console.log("displayPubList");
if (typeof store == 'undefined')
store = getObjectStore(DB_STORE_NAME, 'readonly');
var pub_msg = $('#pub-msg');
pub_msg.empty();
var pub_list = $('#pub-list');
pub_list.empty();
// Resetting the iframe so that it doesn't display previous content
newViewerFrame();
var req;
req = store.count();
// Requests are executed in the order in which they were made against the
// transaction, and their results are returned in the same order.
// Thus the count text below will be displayed before the actual pub list
// (not that it is algorithmically important in this case).
req.onsuccess = function(evt) {
pub_msg.append('<p>There are <strong>' + evt.target.result +
'</strong> record(s) in the object store.</p>');
};
req.onerror = function(evt) {
console.error("add error", this.error);
displayActionFailure(this.error);
};
var i = 0;
req = store.openCursor();
req.onsuccess = function(evt) {
var cursor = evt.target.result;
// If the cursor is pointing at something, ask for the data
if (cursor) {
console.log("displayPubList cursor:", cursor);
req = store.get(cursor.key);
req.onsuccess = function (evt) {
var value = evt.target.result;
var list_item = $('<li>' +
'[' + cursor.key + '] ' +
'(biblioid: ' + value.biblioid + ') ' +
value.title +
'</li>');
if (value.year != null)
list_item.append(' - ' + value.year);
if (value.hasOwnProperty('blob') &&
typeof value.blob != 'undefined') {
var link = $('<a href="' + cursor.key + '">File</a>');
link.on('click', function() { return false; });
link.on('mouseenter', function(evt) {
setInViewer(evt.target.getAttribute('href')); });
list_item.append(' / ');
list_item.append(link);
} else {
list_item.append(" / No attached file");
}
pub_list.append(list_item);
};
// Move on to the next object in store
cursor.continue();
// This counter serves only to create distinct ids
i++;
} else {
console.log("No more entries");
}
};
}
function newViewerFrame() {
var viewer = $('#pub-viewer');
viewer.empty();
var iframe = $('<iframe />');
viewer.append(iframe);
return iframe;
}
function setInViewer(key) {
console.log("setInViewer:", arguments);
key = Number(key);
if (key == current_view_pub_key)
return;
current_view_pub_key = key;
var store = getObjectStore(DB_STORE_NAME, 'readonly');
getBlob(key, store, function(blob) {
console.log("setInViewer blob:", blob);
var iframe = newViewerFrame();
// It is not possible to set a direct link to the
// blob to provide a mean to directly download it.
if (blob.type == 'text/html') {
var reader = new FileReader();
reader.onload = (function(evt) {
var html = evt.target.result;
iframe.load(function() {
$(this).contents().find('html').html(html);
});
});
reader.readAsText(blob);
} else if (blob.type.indexOf('image/') == 0) {
iframe.load(function() {
var img_id = 'image-' + key;
var img = $('<img id="' + img_id + '"/>');
$(this).contents().find('body').html(img);
var obj_url = window.URL.createObjectURL(blob);
$(this).contents().find('#' + img_id).attr('src', obj_url);
window.URL.revokeObjectURL(obj_url);
});
} else if (blob.type == 'application/pdf') {
$('*').css('cursor', 'wait');
var obj_url = window.URL.createObjectURL(blob);
iframe.load(function() {
$('*').css('cursor', 'auto');
});
iframe.attr('src', obj_url);
window.URL.revokeObjectURL(obj_url);
} else {
iframe.load(function() {
$(this).contents().find('body').html("No view available");
});
}
});
}
/**
* @param {string} biblioid
* @param {string} title
* @param {number} year
* @param {string} url the URL of the image to download and store in the local
* IndexedDB database. The resource behind this URL is subjected to the
* "Same origin policy", thus for this method to work, the URL must come from
* the same origin as the web site/app this code is deployed on.
*/
function addPublicationFromUrl(biblioid, title, year, url) {
console.log("addPublicationFromUrl:", arguments);
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
// Setting the wanted responseType to "blob"
// http://www.w3.org/TR/XMLHttpRequest2/#the-response-attribute
xhr.responseType = 'blob';
xhr.onload = function (evt) {
if (xhr.status == 200) {
console.log("Blob retrieved");
var blob = xhr.response;
console.log("Blob:", blob);
addPublication(biblioid, title, year, blob);
} else {
console.error("addPublicationFromUrl error:",
xhr.responseText, xhr.status);
}
};
xhr.send();
// We can't use jQuery here because as of jQuery 1.8.3 the new "blob"
// responseType is not handled.
// http://bugs.jquery.com/ticket/11461
// http://bugs.jquery.com/ticket/7248
// $.ajax({
// url: url,
// type: 'GET',
// xhrFields: { responseType: 'blob' },
// success: function(data, textStatus, jqXHR) {
// console.log("Blob retrieved");
// console.log("Blob:", data);
// // addPublication(biblioid, title, year, data);
// },
// error: function(jqXHR, textStatus, errorThrown) {
// console.error(errorThrown);
// displayActionFailure("Error during blob retrieval");
// }
// });
}
/**
* @param {string} biblioid
* @param {string} title
* @param {number} year
* @param {Blob=} blob
*/
function addPublication(biblioid, title, year, blob) {
console.log("addPublication arguments:", arguments);
var obj = { biblioid: biblioid, title: title, year: year };
if (typeof blob != 'undefined')
obj.blob = blob;
var store = getObjectStore(DB_STORE_NAME, 'readwrite');
var req;
try {
req = store.add(obj);
} catch (e) {
if (e.name == 'DataCloneError')
displayActionFailure("This engine doesn't know how to clone a Blob, " +
"use Firefox");
throw e;
}
req.onsuccess = function (evt) {
console.log("Insertion in DB successful");
displayActionSuccess();
displayPubList(store);
};
req.onerror = function() {
console.error("addPublication error", this.error);
displayActionFailure(this.error);
};
}
/**
* @param {string} biblioid
*/
function deletePublicationFromBib(biblioid) {
console.log("deletePublication:", arguments);
var store = getObjectStore(DB_STORE_NAME, 'readwrite');
var req = store.index('biblioid');
req.get(biblioid).onsuccess = function(evt) {
if (typeof evt.target.result == 'undefined') {
displayActionFailure("No matching record found");
return;
}
deletePublication(evt.target.result.id, store);
};
req.onerror = function (evt) {
console.error("deletePublicationFromBib:", evt.target.errorCode);
};
}
/**
* @param {number} key
* @param {IDBObjectStore=} store
*/
function deletePublication(key, store) {
console.log("deletePublication:", arguments);
if (typeof store == 'undefined')
store = getObjectStore(DB_STORE_NAME, 'readwrite');
// As per spec http://www.w3.org/TR/IndexedDB/#object-store-deletion-operation
// the result of the Object Store Deletion Operation algorithm is
// undefined, so it's not possible to know if some records were actually
// deleted by looking at the request result.
var req = store.get(key);
req.onsuccess = function(evt) {
var record = evt.target.result;
console.log("record:", record);
if (typeof record == 'undefined') {
displayActionFailure("No matching record found");
return;
}
// Warning: The exact same key used for creation needs to be passed for
// the deletion. If the key was a Number for creation, then it needs to
// be a Number for deletion.
req = store.delete(key);
req.onsuccess = function(evt) {
console.log("evt:", evt);
console.log("evt.target:", evt.target);
console.log("evt.target.result:", evt.target.result);
console.log("delete successful");
displayActionSuccess("Deletion successful");
displayPubList(store);
};
req.onerror = function (evt) {
console.error("deletePublication:", evt.target.errorCode);
};
};
req.onerror = function (evt) {
console.error("deletePublication:", evt.target.errorCode);
};
}
function displayActionSuccess(msg) {
msg = typeof msg != 'undefined' ? "Success: " + msg : "Success";
$('#msg').html('<span class="action-success">' + msg + '</span>');
}
function displayActionFailure(msg) {
msg = typeof msg != 'undefined' ? "Failure: " + msg : "Failure";
$('#msg').html('<span class="action-failure">' + msg + '</span>');
}
function resetActionStatus() {
console.log("resetActionStatus ...");
$('#msg').empty();
console.log("resetActionStatus DONE");
}
function addEventListeners() {
console.log("addEventListeners");
$('#register-form-reset').click(function(evt) {
resetActionStatus();
});
$('#add-button').click(function(evt) {
console.log("add ...");
var title = $('#pub-title').val();
var biblioid = $('#pub-biblioid').val();
if (!title || !biblioid) {
displayActionFailure("Required field(s) missing");
return;
}
var year = $('#pub-year').val();
if (year != '') {
// Better use Number.isInteger if the engine has EcmaScript 6
if (isNaN(year)) {
displayActionFailure("Invalid year");
return;
}
year = Number(year);
} else {
year = null;
}
var file_input = $('#pub-file');
var selected_file = file_input.get(0).files[0];
console.log("selected_file:", selected_file);
// Keeping a reference on how to reset the file input in the UI once we
// have its value, but instead of doing that we rather use a "reset" type
// input in the HTML form.
//file_input.val(null);
var file_url = $('#pub-file-url').val();
if (selected_file) {
addPublication(biblioid, title, year, selected_file);
} else if (file_url) {
addPublicationFromUrl(biblioid, title, year, file_url);
} else {
addPublication(biblioid, title, year);
}
});
$('#delete-button').click(function(evt) {
console.log("delete ...");
var biblioid = $('#pub-biblioid-to-delete').val();
var key = $('#key-to-delete').val();
if (biblioid != '') {
deletePublicationFromBib(biblioid);
} else if (key != '') {
// Better use Number.isInteger if the engine has EcmaScript 6
if (key == '' || isNaN(key)) {
displayActionFailure("Invalid key");
return;
}
key = Number(key);
deletePublication(key);
}
});
$('#clear-store-button').click(function(evt) {
clearObjectStore();
});
var search_button = $('#search-list-button');
search_button.click(function(evt) {
displayPubList();
});
}
openDb();
addEventListeners();
})(); // Immediately-Invoked Function Expression (IIFE)
一些文档及说明
3.数据的增、删、改、查 // 增: 添加数据,重复添加会报错 addData:function(db,storename,data){ var store = store = db.transaction(storename,'readwrite').objectStore(storename),request; for(var i = 0 ; i < data.length;i++){ request = store.add(data[i]); request.onerror = function(){ console.error('add添加数据库中已有该数据') }; request.onsuccess = function(){ console.log('add添加数据已存入数据库') }; } }
// 删 deleteData:function(db,storename,key){ var store = store = db.transaction(storename,'readwrite').objectStore(storename); store.delete(key) console.log('已删除存储空间'+storename+'中'+key+'记录'); }
// 改 putData:function(db,storename,data){ var store = store = db.transaction(storename,'readwrite').objectStore(storename),request; for(var i = 0 ; i < data.length;i++){ request = store.put(data[i]); request.onerror = function(){ console.error('put添加数据库中已有该数据') }; request.onsuccess = function(){ console.log('put添加数据已存入数据库') }; } }
// 查 getDataByKey:function(db,storename,key){ var store = db.transaction(storename,'readwrite').objectStore(storename); var request = store.get(key); request.onerror = function(){ console.error('getDataByKey error'); }; request.onsuccess = function(e){ var result = e.target.result; console.log('查找数据成功') console.log(result); }; }
个人初步试用
IndexedDB
目录:在Windows中,该文件位于:
Linux位于
indexedDB使用场景