问题描述
有没有办法存储用户想要上传但没有互联网连接(它是 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 浏览器)在网络再次可用时处理自动上传会很有帮助。