如您所知,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 条评论