HTML5 本地儲存初探
隨著html5本地儲存的到來,web應用也會更加充滿活力。下面是個人對html5本地儲存的一些理解。
客戶端持久化資料的歷史:
HTTP cookie: 這個是客戶端使用的最為通用的方式,但問題也很明顯。典型情景是使用者本想執行一個事務,但可能會因為cookie而在不同視窗中執行多個事務。例如,一個使用者在兩個不同的視窗中登入同一個網站購買機票。網站使用cookie來記錄使用者購買的車票,當用戶在不同視窗之間點選時,cookie可能會導致使用者為同一個航班購買兩張機票。另外,cookie最多隻能儲存4KB資料,每個HTTP請求都要將其送回伺服器。
我們真正想要的是:
-
更大的儲存空間
-
客戶端持久化
-
不受頁面重新整理的影響
-
不需要提交到伺服器
HTML5本地儲存:
Web Storage是目前支援最廣泛的HTML5本地儲存規範,幾乎所有瀏覽器都支援。
瀏覽器通過實現localStorage等介面來支援webStorage。它讓 web 頁面能夠以鍵值對的形式,在客戶端web瀏覽器中將資料儲存在本地的方法。就像 cookie 一樣,這種資料在你離開 web 站點、關閉標籤頁、退出瀏覽器等等的時候依然儲存。不同於 cookie 的地方是,這個資料不會被髮送到遠端 web 伺服器(除非你自己手動傳送)。
其使用非常簡單:
var foo = "hello,localStorage"; localStorage.setItem("hello",foo); var message = localStorage.getItem("hello");
通過註冊“storage”事件可以感知資料值的變化。
window.addEventListener('storage', function(e) {
console.log(e.key + "'s value is changed from '" +
e.oldValue + "' to '" + e.newValue + "' by " + e.url);
}, false);
//A page
localStorage['foo'] = 'bar';
//B page
localStorage['foo'] = 'newBar'
FileSystem API
當我們不滿足於鍵-值形式的本地儲存,而是想要自己管理本地儲存;或者覺得資料庫的支援不夠好,想擁有一個本地檔案系統一樣時,可能要考慮FileSystem API了。目前,只有chrome瀏覽器支援該特性。使用FileSystem API,web應用可以建立、讀寫、遍歷存在於沙箱(sandbox)中的使用者本地檔案系統的子集。
典型的好處如下:
1. 持久上傳
- 當檔案或者目錄被選擇上傳時,資料被拷貝到本地沙箱中,並且一次上傳一部分。
- 可以在瀏覽器崩潰或者網路故障後重新啟動上傳。
2. 視訊遊戲等擁有大量多媒體資源的應用
- 下載壓縮包,本地解壓成目錄結構。
- 下載與作業系統無關
- 支援預取策略,從而使體驗更加流暢。
- 伺服器端更加節省儲存。
3. 音訊、圖片離線編輯、快取加速
- 目錄結構更加適合於該型別檔案的組織。
- 被其他應用如iTunes、Picasa離線編輯
4. 離線視訊觀看
- 為後續的觀看下載超過1GB的大檔案。
- 方便快速seek播放
- 部分播放,不用video標籤全部載入
5. 離線web 郵件客戶端
- 下載附件,本地儲存。
- 快取使用者選擇的附件以便快速上傳。
- 上傳時可以作為多部分的post,而不是一次一個XHR裡面的檔案。
FileSystem API 程式碼示例,需要chrome以--unlimited-quota-for-files標誌執行,或者chrome web app 的manifest中開啟unlimitedStorage許可權
<!DOCTYPE html>
<html>
<head>
<style>
.example {
padding: 10px;
border: 1px solid #CCC;
}
#example-list-fs ul {
padding-left: 0;
}
#example-list-fs li {
list-style: none;
}
#example-list-fs img {
vertical-align: middle;
}
button {
padding: 5px 8px;
cursor: pointer;
text-shadow: 1px 1px white;
font-weight: 700;
font-size: 10pt;
}
body {
font: 14px Arial;
}
</style>
</head>
<body>
<div id="example-list-fs" class="example">
<button>Add some files</button> <button>List files</button> <button>Remove all files</button>
<ul id="example-list-fs-ul"></ul>
</div>
<script>
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
var fs = null;
function errorHandler(e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
document.querySelector('#example-list-fs-ul').innerHTML = 'Error: ' + msg;
}
function initFS() {
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(filesystem) {
fs = filesystem;
}, errorHandler);
}
var buttons = document.querySelectorAll('#example-list-fs button');
var filelist = document.querySelector('#example-list-fs-ul');
if (buttons.length >= 3) {
buttons[0].addEventListener('click', function(e) {
if (!fs) {
return;
}
fs.root.getFile('log.txt', {create: true}, null, errorHandler);
fs.root.getFile('song.mp3', {create: true}, null, errorHandler);
fs.root.getDirectory('mypictures', {create: true}, null, errorHandler);
filelist.innerHTML = 'Files created.';
}, false);
buttons[1].addEventListener('click', function(e) {
if (!fs) {
return;
}
var dirReader = fs.root.createReader();
dirReader.readEntries(function(entries) {
if (!entries.length) {
filelist.innerHTML = 'Filesystem is empty.';
} else {
filelist.innerHTML = '';
}
var fragment = document.createDocumentFragment();
for (var i = 0, entry; entry = entries[i]; ++i) {
var img = entry.isDirectory ? '<img src="http://www.html5rocks.com/static/images/icon-folder.gif">' :
'<img src="http://www.html5rocks.com/static/images/icon-file.gif">';
var li = document.createElement('li');
li.innerHTML = [img, '<span>', entry.name, '</span>'].join('');
fragment.appendChild(li);
}
filelist.appendChild(fragment);
}, errorHandler);
}, false);
buttons[2].addEventListener('click', function(e) {
if (!fs) {
return;
}
var dirReader = fs.root.createReader();
dirReader.readEntries(function(entries) {
for (var i = 0, entry; entry = entries[i]; ++i) {
if (entry.isDirectory) {
entry.removeRecursively(function() {}, errorHandler);
} else {
entry.remove(function() {}, errorHandler);
}
}
filelist.innerHTML = 'Directory emptied.';
}, errorHandler);
}, false);
}
// Initiate filesystem on page load.
if (window.requestFileSystem) {
initFS();
}
</script>
</body>
</html>
綜上,HTML5的本地儲存特性,將會給未來的web應用帶來更豐富的特性,從而大幅提升使用者體驗。
參考資料: