fm: store file to OPFS temporarily (#413)

This commit is contained in:
UUBulb
2024-08-21 22:19:40 +08:00
committed by GitHub
parent 0ec1bb2c54
commit cae443d5c8
2 changed files with 112 additions and 56 deletions

70
resource/static/file.js Normal file
View File

@@ -0,0 +1,70 @@
let receivedLength = 0;
let expectedLength = 0;
let root;
let draftHandle;
let accessHandle;
const Operation = Object.freeze({
WriteHeader: 1,
WriteChunks: 2,
DeleteFiles: 3
});
onmessage = async function (event) {
try {
const { operation, arrayBuffer, fileName } = event.data;
switch (operation) {
case Operation.WriteHeader: {
const dataView = new DataView(arrayBuffer);
expectedLength = Number(dataView.getBigUint64(4, false));
receivedLength = 0;
// Create a new temporary file
root = await navigator.storage.getDirectory();
draftHandle = await root.getFileHandle(fileName, { create: true });
accessHandle = await draftHandle.createSyncAccessHandle();
// Inform that file handle is created
const dataChunk = arrayBuffer.slice(12);
receivedLength += dataChunk.byteLength;
accessHandle.write(dataChunk, { at: 0 });
const progress = 'got handle';
postMessage({ type: 'progress', progress: progress });
break;
}
case Operation.WriteChunks: {
if (!accessHandle) {
throw new Error('accessHandle is undefined');
}
const dataChunk = arrayBuffer;
accessHandle.write(dataChunk, { at: receivedLength });
receivedLength += dataChunk.byteLength;
if (receivedLength === expectedLength) {
accessHandle.flush();
accessHandle.close();
const fileBlob = await draftHandle.getFile();
const blob = new Blob([fileBlob], { type: 'application/octet-stream' });
postMessage({ type: 'result', blob: blob, fileName: fileName });
}
break;
}
case Operation.DeleteFiles: {
for await (const [name, handle] of root.entries()) {
if (handle.kind === 'file') {
await root.removeEntry(name);
} else if (handle.kind === 'directory') {
await root.removeEntry(name, { recursive: true });
}
}
break;
}
}
} catch (error) {
postMessage({ error: error.message });
}
};