To *_* Be 3 html javascript caching local-storage typescript
我正在开发从在线服务器下载文件的 ionic 2 应用程序,我想将这些文件存储到本地存储(或我不知道的缓存)。
我知道我可以使用以下方法将数据存储到本地存储:
localStorage.setItem('key','value');
Run Code Online (Sandbox Code Playgroud)
但是如果是文件,特别是大文件,如何存储到本地存储呢?
注意:我正在使用 TypeScript。
Dai*_*Dai 29
截至 2022 年初,IndexedDB 仍然是持久保存二进制数据(例如图像和视频、来自<input type="file">JSFile和Blob对象的用户文件等)的最佳整体选择,因为它支持异步 IO 并且能够保存原始二进制数据,而无需丑陋的黑客攻击就像 URI 的 Base64 编码一样data:。
然而,IndexedDB 可能是 HTML5 中设计最差的 API 接口之一( “触发事件后,你连接事件处理程序?太疯狂了! ”),浏览器供应商也同意:所以 Apple 的 Safari 和 Google 的 Chromium 现在都一样支持一个更简单的数据持久化 API,名为Origin Private File System (OPFS),该 API 最近于 2021 年推出。
OPFS 是较大的 WHATWG 文件系统 API的子集,也与现有的 WHATWG 存储 API(定义localStorage、indexedDB等)相关。
尽管 OPFS 的名称包含术语“文件系统”,但 OPFS不涉及对用户实际本地计算机文件系统的任何访问:将其更多地视为一个隔离的虚拟或“假装”文件系统,其范围仅限于单个网站(特别是,范围仅限于单一来源),因此不同网站/来源无法访问其他网站的 OPFS 存储。
OPFS 缺乏初始固定大小的存储配额,而localStorage和sessionStorage两者都有 5MB 的初始限制。
QuotaExceededError您应该准备好妥善处理。由于 OPFS 不涉及用户实际的本地文件系统,并且空间是按来源隔离的(URI 方案 + 主机名 + 端口),这意味着 OPFS 不会带来用户隐私或计算机安全的风险,因此浏览器不会中断您的脚本,向您的用户显示可能看起来很吓人的安全提示,用户必须点击才能明确授予或拒绝您的网站或页面使用 OPFS API 的能力。
indexedDB一样localStorage,甚至假装在页面加载或会话之间保留数据(例如 Chrome 的隐身模式)。简单介绍一下:您使用 OPFS vianavigator.storage和 waitinggetDirectory()来获取FileSystemHandle代表网站(源)存储空间的根目录的对象,然后在根上使用 wait 方法来创建和操作文件和子目录。
例如,假设您有一个<canvas>元素,其中包含用户手绘的一些非常棒的原创艺术作品,并且希望将其作为 PNG blob 本地保存在浏览器的 OPFS 存储空间中,那么您可以执行以下操作:
async function doOpfsDemo() {
// Open the "root" of the website's (origin's) private filesystem:
let storageRoot = null;
try {
storageRoot = await navigator.storage.getDirectory();
}
catch( err ) {
console.error( err );
alert( "Couldn't open OPFS. See browser console.\n\n" + err );
return;
}
// Get the <canvas> element from the page DOM:
const canvasElem = document.getElementById( 'myCanvas' );
// Save the image:
await saveCanvasToPngInOriginPrivateFileSystem( storageRoot, canvasElem );
// (Re-)load the image:
await loadPngFromOriginPrivateFileSystemIntoCanvas( storageRoot, canvasElem );
}
async function saveCanvasToPngInOriginPrivateFileSystem( storageRoot, canvasElem ) {
// Save the <canvas>'s image to a PNG file to an in-memory Blob object: (see https://stackoverflow.com/a/57942679/159145 ):
const imagePngBlob = await new Promise(resolve => canvasElem.toBlob( resolve, 'image/png' ) );
// Create an empty (zero-byte) file in a new subdirectory: "art/mywaifu.png":
const newSubDir = await storageRoot.getDirectoryHandle( "art", { "create" : true });
const newFile = await newSubDir.getFileHandle( "mywaifu.png", { "create" : true });
// Open the `mywaifu.png` file as a writable stream ( FileSystemWritableFileStream ):
const wtr = await newFile.createWritable();
try {
// Then write the Blob object directly:
await wtr.write( imagePngBlob );
}
finally {
// And safely close the file stream writer:
await wtr.close();
}
}
async function loadPngFromOriginPrivateFileSystemIntoCanvas( storageRoot, canvasElem ) {
const artSubDir = await storageRoot.getDirectoryHandle( "art" );
const savedFile = await artSubDir.getFileHandle( "mywaifu.png" ); // Surprisingly there isn't a "fileExists()" function: instead you need to iterate over all files, which is odd... https://wicg.github.io/file-system-access/
// Get the `savedFile` as a DOM `File` object (as opposed to a `FileSystemFileHandle` object):
const pngFile = await savedFile.getFile();
// Load it into an ImageBitmap object which can be painted directly onto the <canvas>. You don't need to use URL.createObjectURL and <img/> anymore. See https://developer.mozilla.org/en-US/docs/Web/API/createImageBitmap
// But you *do* still need to `.close()` the ImageBitmap after it's painted otherwise you'll leak memory. Use a try/finally block for that.
try {
const loadedBitmap = await createImageBitmap( pngFile ); // `createImageBitmap()` is a global free-function, like `parseInt()`. Which is unusual as most modern JS APIs are designed to not pollute the global scope.
try {
const ctx = canvasElem.getContext('2d');
ctx.clearRect( /*x:*/ 0, /*y:*/ 0, ctx.canvas.width, ctx.canvas.height ); // Clear the canvas before drawing the loaded image.
ctx.drawImage( loadedBitmap, /*x:*/ 0, /*y:*/ 0 ); // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
}
finally {
loadedBitmap.close(); // https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap/close
}
}
catch( err ) {
console.error( err );
alert( "Couldn't load previously saved image into <canvas>. See browser console.\n\n" + err );
return;
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,OPFS 文件系统空间并不代表用户计算机上的底层文件系统(如果有)FileSystemFileHandle : OPFS 空间中的现有文件不一定存在于用户的真实文件系统中。
C:\Users\{you}\AppData\Local\Google\Chrome\User Data\Default\IndexedDB.OPFS 也非常简单:虽然计算机的 NTFS、ZFS 或 APFS 文件系统将具有权限/ACL、所有权、低级(即块级)访问、快照和历史记录等功能,但 OPFS 缺乏所有这些功能。这些:OPFS 甚至没有文件锁定机制,这通常被认为是基本的原始 FS 操作。
但不要将 OPFS 与其他文件系统和文件系统式 API 混淆:
Window.showOpenFilePicker())在现实情况下得到了广泛支持恰恰相反。<input type="file">in HTML 和HTMLInputElement.filesin 脚本允许页面提示用户选择单个现有文件或多个文件(使用<input type="file" multiple>,甚至整个目录树- 所有这些都通过File界面将这些文件公开给页面脚本。chrome.fileSystemAPI最初用于Chrome 应用程序和浏览器扩展,网页脚本也可以通过window.requestFileSystem()或window.webkitRequestFileSystem()使用它。File接口。
HTMLAnchorElement.download,这听起来很尴尬。createWritable/FileSystemWritableFileStream创建、截断、编辑和附加到现有文件,但目前只有基于 Chromium 的浏览器支持它(因此不支持 Firefox 或 Safari)。<div>浏览器窗口中的网页中的某些用例的用例):和events 脚本可以访问拖动的数据,这些数据可以是文件,但也可以是其他类型的数据)
drag。dragoverHTMLInputElement.files此类似,它不会授予对用户拖放的任何文件的任何写入访问权限。| 归档时间: |
|
| 查看次数: |
3230 次 |
| 最近记录: |