是否可以将 File 对象保存在 LocalStorage 中,然后当用户返回页面时通过 FileReader 重新加载文件?

Posted

技术标签:

【中文标题】是否可以将 File 对象保存在 LocalStorage 中,然后当用户返回页面时通过 FileReader 重新加载文件?【英文标题】:Is it possible to save a File object in LocalStorage and then reload a File via FileReader when a user comes back to a page? 【发布时间】:2011-09-03 18:27:16 【问题描述】:

例如,假设用户将一些非常大的图像或媒体文件加载到您的网络应用程序中。当他们返回时,您希望您的应用程序显示他们之前加载的内容,但由于数据太大而无法将实际文件数据保留在 LocalStorage 中。

【问题讨论】:

您是否在应用中使用客户端 Java? 这是 javascript,不是 Java。 你知道 Firebase 吗?也许这个问题可以帮助你。 ***.com/questions/13955813/… 【参考方案1】:

localStorage不可能做到这一点。存储在localStorage 中的数据需要是可序列化的原始类型之一。这不包括 File 对象。

例如,这将不会按您的预期工作:

var el = document.createElement('input');
el.type='file';
el.onchange = function(e) 
  localStorage.file = JSON.stringify(this.files[0]);
  // LATER ON...
  var reader = new FileReader();
  reader.onload = function(e) 
    var result = this.result; // never reaches here.
  ;
  reader.readAsText(JSON.parse(localStorage.f));
;
document.body.appendChild(el);

解决方案是使用更强大的存储选项,例如将文件内容写入html5 Filesystem 或将其存储在IndexedDB 中。

【讨论】:

这在技术上实际上是可行的,如果您保存的图像文件较小,甚至可能是一个可行的解决方案。看我的回答。 这个答案是完全错误的。请参阅下面的回答,了解实现此目的的几种方法。 2019,可能的解决方案,见***.com/questions/19119040/…【参考方案2】:

如果您只需要将小文件保存在 localStorage 中,从技术上讲您可以。

只是base64,因为它是一个字符串......它是本地存储友好的。

我认为 localStorage 的限制约为 5MB。 base64 字符串的文件大小非常小,因此这是一种存储小图像的可行方法。如果你使用这个懒人的方式,缺点是你必须注意 5MB 的限制。我认为这可能是一个解决方案,具体取决于您的需求。

【讨论】:

【参考方案3】:

是的,这是可能的。您可以将有关文件的任何信息插入到 LocalStorage,前提是您将其序列化为支持的原始类型之一。您还可以将整个文件序列化到 LocalStorage 中,如果需要,稍后再检索,但文件大小有限制,具体取决于浏览器。

下面展示了如何使用两种不同的方法来实现这一点:

(function () 
// 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
        try 
            localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
        
        catch (e) 
                console.log("Storage failed: " + e);                
        
    , false);

    // Set initial image src    
    elephant.setAttribute("src", "elephant.png");

else 
    // Use image from localStorage
    elephant.setAttribute("src", storageFiles.elephant);


// 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, BlobBuilder 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 BlobBuilder 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
                try 
                    localStorage.setItem("rhino", result);
                
                catch (e) 
                    console.log("Storage failed: " + e);
                
            ;
            // Load blob as Data URL
            fileReader.readAsDataURL(blob);
        
    , false);
    // Send XHR
    xhr.send();

)();

Source

【讨论】:

以上是关于是否可以将 File 对象保存在 LocalStorage 中,然后当用户返回页面时通过 FileReader 重新加载文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在本地存储中保存和恢复 File 对象

C#程序将对象保存为json文件的方法

序列化:pickle 模块

IO流之File类

Python中使用pickle持久化对象

Python中Pickle模块的dump()方法和load()方法