WASM与OPFS组合技系列一(文件导入)

简介

wasm(WebAssembly)和OPFS(Origin Private File System)是前端在进行科学计算和大文件处理时常用的技术,本系列就着重介绍怎么将两种技术组合来实现大文件计算的同时保持高效率和低内存效果。

OPFS介绍

OPFS 全称为 Origin-Private File System (源私有文件系统),是浏览器提供的一种新型 Web API,允许网页在用户设备上创建和管理一个私有的、与网站源(Origin)绑定的虚拟文件系统 。它是现代浏览器支持的标准技术,旨在解决 Web 应用对文件高效读写的需求(尤其是大文件和二进制数据)。

通过Can I Use可以看到,目前除了IE,其他主流浏览器都已支持该特性,可以放心使用。

OPFS本身对于文件读写支持同步和异步两种模式,主线中使用时只可以使用异步,WebWorker中两种模式都可以正常使用。

文件导入示例

本期着重介绍怎么将用户文件写入到OPFS中。

1、获取文件对象

通过简单的<input type="file" />控件可以获取到文件对象。

2、将文件对象发送到独立线程中

js 复制代码
const uploadFile = () => {
    const uploadFile = document.getElementById("file").files[0];
    if (!uploadFile) {
      alert("请选择需要上传的文件");
      return;
    }
    worker.postMessage({
      type: "copy",
      file: uploadFile,
    });
};

3、在线程中将文件切片保存到OPFS中

js 复制代码
const copyFileToOPFS = async (file) => {
  Module.print("准备上传文件:", file.name);
  // 线程中可以直接使用同步文件读取
  const fileReader = new FileReaderSync();
  const filename = file.name;
  // 获取OPFS根目录
  const root = await navigator.storage.getDirectory();
  // 获取文件句柄
  const fileHandle = await root.getFileHandle(filename, {
    create: true, // 如果没有文件则创建一个新文件
  });
  // 获取文件同步写句柄,只可以在worker中使用
  const accessHandle = await fileHandle.createSyncAccessHandle();
  let times = 0;
  let index = 0;
  const length = 1024 * 1024 * 50;
  let flag = true;
  const fileSize = file.size;
  while (flag) {
    times++;
    if (times > 1000) {
      flag = false;
      break;
    }
    if (index >= fileSize) {
      flag = false;
      break;
    }
    const start = index;
    let end = index + length;
    if (end > fileSize) {
      end = fileSize;
    }
    // 获取文件切片
    const content = file.slice(start, end);
    // 读取为ArrayBuffer
    let arrayBuffer = fileReader.readAsArrayBuffer(content);
    // 将数据写入文件
    accessHandle.write(arrayBuffer, {
      at: start, // 文件内字节下标,主要用于分片写入文件
    });
    // 将数据刷入文件中,只有执行了flush数据才会真实保存到文件中
    accessHandle.flush();
    arrayBuffer = null;
    index = end;
    Module.print("文件已上传:", ((index / fileSize) * 100).toFixed(2), "%");
  }
  // 此处必须关闭文件句柄,不然会导致后续无法再次获取句柄
  accessHandle.close();
  Module.print("文件上传成功: " + file.name);
};

源码示例

github.com/yangyanggu/...

相关推荐
kooboo china.1 小时前
Tailwind css实战,基于Kooboo构建AI对话框页面(二)
前端·css
啃火龙果的兔子2 小时前
判断手机屏幕上的横向滑动(左滑和右滑)
javascript·react.js·智能手机
yuanmenglxb20044 小时前
react基础技术栈
前端·javascript·react.js
coding随想4 小时前
从SPDY到HTTP/2:网络协议的革新与未来
javascript
Magnum Lehar5 小时前
vulkan游戏引擎vulkan部分的fence实现
java·前端·游戏引擎
一枚码农4045 小时前
使用pnpm、vite搭建Phaserjs的开发环境
javascript·游戏·vite·phaserjs
FreeBuf_5 小时前
恶意npm与VS Code包窃取数据及加密货币资产
前端·npm·node.js
agenIT6 小时前
vue3 getcurrentinstance 用法
javascript·vue.js·ecmascript
天天打码6 小时前
npm/yarn/pnpm安装时Sharp模块报错解决方法
前端·npm·node.js
码农捻旧6 小时前
JavaScript 性能优化按层次逐步分析
开发语言·前端·javascript·性能优化