如您所知,localStorage 在将信息快速存储在用户的 Web 浏览器中方面非常强大,并且在所有 Web 浏览器中也存在了很长时间。但是,我们如何在其中存储文件呢?
请务必阅读 在 IndexedDB 中存储图片和文件.
使用 JSON 实现强大的控制
让我们从关于 localStorage 的一些基本信息开始。在 localStorage 中存储信息时,您使用键值对,如下所示
localStorage.setItem("name", "Robert");
要读取它,您只需获取该键的值
localStorage.getItem("name");
这很好,并且能够保存至少 5 MB,您有很多选择。但是,由于 localStorage 只是基于字符串的,因此保存一个没有结构形式的长字符串并不是最佳选择。
因此,我们可以利用 Web 浏览器中的原生 JSON 支持将 JavaScript 对象转换为字符串以进行保存,并在读取时将其转换回对象
var cast = {
"Adm. Adama" : "Edward James Olmos",
"President Roslin" : "Mary McDonnell",
"Captain Adama" : "Jamie Bamber",
"Gaius Baltar" : "James Callis",
"Number Six" : "Tricia Helfer",
"Kara Thrace" : " Katee Sackhoff"
};
// Stores the JavaScript object as a string
localStorage.setItem("cast", JSON.stringify(cast));
// Parses the saved string into a JavaScript object again
JSON.parse(localStorage.getItem("cast"));
存储图片
这里的想法是能够获取已加载到当前网页中的图片并将其存储到 localStorage 中。正如我们在上面所述,localStorage 仅支持字符串,因此我们需要做的是将图片转换为 Data URL。对图片执行此操作的一种方法是将其加载到 canvas 元素 中。然后,使用 canvas,您可以将当前的视觉表示形式从 canvas 读取为 Data URL。
让我们看一下这个示例,其中我们在文档中有一个 id 为“elephant”的图片
// Get a reference to the image element
var elephant = document.getElementById("elephant");
// Take action when the image has loaded
elephant.addEventListener("load", function () {
var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");
// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
// Draw image into canvas element
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
// Get canvas contents as a data URL
var imgAsDataURL = imgCanvas.toDataURL("image/png");
// Save image into localStorage
localStorage.setItem("elephant", imgAsDataURL);
}, false);
然后,如果我们想更进一步,我们可以利用一个 JavaScript 对象,并对 localStorage 进行日期检查。在这个例子中,我们第一次通过 JavaScript 从服务器加载图片,但是对于之后每次页面加载,我们都会从 localStorage 读取保存的图片
HTML
<figure>
<img id="elephant" src="about:blank" alt="A close up of an elephant">
<noscript>
<img src="elephant.png" alt="A close up of an elephant">
</noscript>
<figcaption>A mighty big elephant, and mighty close too!</figcaption>
</figure>
JavaScript
// localStorage with image
var storageFiles = JSON.parse(localStorage.getItem("storageFiles")) || {},
elephant = document.getElementById("elephant"),
storageFilesDate = storageFiles.date,
date = new Date(),
todaysDate = (date.getMonth() + 1).toString() + date.getDate().toString();
// Compare date and create localStorage if it's not existing/too old
if (typeof storageFilesDate === "undefined" || storageFilesDate < todaysDate) {
// Take action when the image has loaded
elephant.addEventListener("load", function () {
var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");
// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
// Draw image into canvas element
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
// Save image as a data URL
storageFiles.elephant = imgCanvas.toDataURL("image/png");
// Set date for localStorage
storageFiles.date = todaysDate;
// Save as JSON in localStorage
localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
}, false);
// Set initial image src
elephant.setAttribute("src", "elephant.png");
}
else {
// Use image from localStorage
elephant.setAttribute("src", storageFiles.elephant);
}
注意:这里需要注意的是,您可能会超过 localStorage 中可用的大小,最好的控制方法是使用 try...catch。
存储任何类型的文件
太好了,我们可以使用 canvas 将图片转换为 Data URL 并保存到 localStorage 中。但是,如果我们想要一个适用于任何类型文件的机制呢?
然后它就会变得有点意思,我们需要使用
基本方法是
- 对文件执行 XMLHttpRequest,并将 responseType 设置为“arraybuffer”
- 将 XMLHttpRequest 的响应(即文件)加载到 Blob 中
- 使用 FileReader 读取该文件并将其加载到页面和/或 localStorage 中
让我们来看一个完整的示例,其中我们请求一个名为“rhino.png”的图片,将其保存到 blob 中,使用 FileReader 读取文件,最后将其保存到 localStorage 中
// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
rhino = document.getElementById("rhino");
if (rhinoStorage) {
// Reuse existing Data URL from localStorage
rhino.setAttribute("src", rhinoStorage);
}
else {
// Create XHR, Blob and FileReader objects
var xhr = new XMLHttpRequest(),
blob,
fileReader = new FileReader();
xhr.open("GET", "rhino.png", true);
// Set the responseType to arraybuffer. "blob" is an option too, rendering manual Blob creation unnecessary, but the support for "blob" is not widespread enough yet
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// Create a blob from the response
blob = new Blob([xhr.response], {type: "image/png"});
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
rhino.setAttribute("src", result);
// Store Data URL in localStorage
localStorage.setItem("rhino", result);
};
// Load blob as Data URL
fileReader.readAsDataURL(blob);
}
}, false);
// Send XHR
xhr.send();
}
使用“blob”作为 responseType
在上面的示例中,我们使用了 responseType“arraybuffer”和一个 Blob 来创建我们可以用于 FileReader 的东西。但是,还有一个名为“blob”的 responseType,它直接返回一个 blob,我们可以将其与 FileReader 一起使用。然后,上面的示例将如下所示
// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
rhino = document.getElementById("rhino");
if (rhinoStorage) {
// Reuse existing Data URL from localStorage
rhino.setAttribute("src", rhinoStorage);
}
else {
// Create XHR and FileReader objects
var xhr = new XMLHttpRequest(),
fileReader = new FileReader();
xhr.open("GET", "rhino.png", true);
// Set the responseType to blob
xhr.responseType = "blob";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
rhino.setAttribute("src", result);
// Store Data URL in localStorage
localStorage.setItem("rhino", result);
};
// Load blob as Data URL
fileReader.readAsDataURL(xhr.response);
}
}, false);
// Send XHR
xhr.send();
}
Web 浏览器支持
- localStorage
- 在所有主要的 Web 浏览器中都已支持很长时间,包括 IE8。
- 原生 JSON 支持
- 与 localStorage 相同的长期支持。
- canvas 元素
- 在大多数主要的 Web 浏览器中都已支持很长时间,但仅从 IE9 开始支持。
- XMLHttpRequest 2 级
- 在 Firefox 和 Google Chrome 中已支持很长时间,在 Safari 5+ 中支持,并计划在 IE10 和 Opera 12 中支持。
- Blob
- 在 Firefox 和 Google Chrome 中已支持很长时间,并计划在 IE10 中支持。也支持 Safari 6.0+ 和 Opera Opera 12.1+
- FileReader
- 在 Firefox 和 Google Chrome 中已支持很长时间,Opera 11.1 开始支持,并计划在 IE10 中支持。Safari 尚不清楚。
- responseType“blob”
- 目前仅在 Firefox 中支持。很快将在 Google Chrome 中支持,并计划在 IE10 中支持。Safari 和 Opera 尚不清楚。
检查和清除 localStorage
检查 localStorage 中内容的最简单方法
- Firebug:DOM 选项卡,然后向下滚动到或搜索 localStorage
- Google Chrome:开发者工具,在“资源”选项卡下
- Opera:在 Opera Dragonfly 的“存储”选项卡中
演示和代码
我创建了一个 使用 localStorage 保存图片和文件的演示,您可以在其中看到 canvas 方法和使用 XMLHtpRequest 2、Blob 和 FileReader 的方法。
用于 在 localStorage 中存储文件 的代码也可以在 GitHub 上找到,现在就去体验一下吧!
关于 Robert Nyman [资深编辑]
Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直在从事网页前端开发工作 - 在瑞典和纽约市。他也定期在 http://robertnyman.com 上发博,喜欢旅行和结识新朋友。
46 条评论