2

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

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

4

1 回答 1

3

有几件事需要考虑。

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

一种更现代但非 Chromium 浏览器当前不支持的方法是使用文件系统访问 API。如本文所述,一旦获得用户的许可,就可以将句柄保存到 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);
  }
});

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

于 2021-02-11T16:20:41.853 回答