保存客户端上传文件的路径或浏览器外的文件供离线使用

问题描述

有没有办法存储用户想要上传但没有互联网连接(它是 PWA)的文件路径,并在连接恢复时重新上传它?或者可能不存储路径,而是将文件保存在浏览器存储之外的用户机器上的某个地方(即使它需要用户的一些接受才能允许浏览器读/写文件),但我不确定它是否是甚至允许这样做。

目前,我将整个文件作为 base64 存储在 IndexedDB 中,但是在读取大文件(大约 100MB)时,它会崩溃/减慢浏览器的速度。另外,我不想让浏览器存储过载。

解决方法

有几件事需要考虑。

将您需要上传的数据存储在 IndexedDB 中,然后在稍后阅读将是最广泛支持的方法。不过,正如您所说,这意味着占用额外的浏览器存储空间。可能有帮助的一件事是先跳过以 Base64 编码文件的步骤,因为在所有现代浏览器中,IndexedDB 很乐意直接为您存储字节 as a Blob

一种更现代但非 Chromium 浏览器目前不支持的方法是使用文件系统访问 API。如this article 中所述,一旦获得用户的许可,您就可以在 IndexedDB 中保存文件的句柄,然后稍后读取该文件(假设基础文件在此期间没有更改)。这样做的好处是不会复制 IndexedDB 中的文件内容,从而节省存储空间。这是从文章中借用的代码片段:

import { get,set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';

const pre = document.querySelector('pre');
const button = document.querySelector('button');

button.addEventListener('click',async () => {
  try {
    // Try retrieving the file handle.
    const fileHandleOrUndefined = await get('file');    
    if (fileHandleOrUndefined) {      
      pre.textContent =
          `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    // This always returns an array,but we just need the first entry.
    const [fileHandle] = await window.showOpenFilePicker();
    // Store the file handle.
    await set('file',fileHandle);    
    pre.textContent =
        `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name,error.message);
  }
});

无论您如何存储文件,使用 Background Sync API 时(同样,目前仅限于 Chromium 浏览器)在网络再次可用时处理自动上传会很有帮助。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...