You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Capacitor Ionic应用写入大PDF时Filesystem.writeFile()崩溃求解决方案

解决Ionic/Capacitor写入大PDF文件崩溃问题

问题根源

你当前的实现通过FileReader将Blob转为base64字符串后写入文件,大体积PDF会触发内存过载崩溃:

  • base64编码会让原数据体积膨胀33%左右,大文件(如50MB+)转码后会占用大量连续内存空间
  • 移动端App内存限制严格,一次性加载并处理整个大文件容易超出阈值

可行解决方案

方案1:直接写入Blob(推荐,Capacitor 3+支持)

Capacitor 3及以上版本的Filesystem.writeFile支持直接传入Blob,无需转base64,大幅降低内存占用:

static async writeAndOpenFile(data: Blob, fileName: string) {
  try {
    const result = await Filesystem.writeFile({
      path: fileName,
      data: data, // 直接传入Blob,跳过base64转码
      directory: Directory.Data,
      recursive: true
    });

    const fileOpener = new FileOpener();
    await fileOpener.open(result.uri, data.type);
    console.log('File is opened');
  } catch (e) {
    console.error('Error handling file:', e);
  }
}

方案2:分块读写大文件(兼容旧版Capacitor)

如果必须使用base64转码,通过分块处理避免一次性加载整个文件到内存:

static async writeAndOpenFile(data: Blob, fileName: string) {
  const chunkSize = 1024 * 1024; // 按1MB分块处理
  const totalChunks = Math.ceil(data.size / chunkSize);
  let offset = 0;

  try {
    // 先创建空文件
    await Filesystem.writeFile({
      path: fileName,
      data: '',
      directory: Directory.Data,
      recursive: true,
      append: false
    });

    // 逐块写入
    for (let i = 0; i < totalChunks; i++) {
      const chunk = data.slice(offset, offset + chunkSize);
      const base64Chunk = await this.blobToBase64(chunk);
      
      await Filesystem.writeFile({
        path: fileName,
        data: base64Chunk,
        directory: Directory.Data,
        append: true // 启用追加模式
      });

      offset += chunkSize;
    }

    // 获取文件URI并打开
    const fileUri = await Filesystem.getUri({
      path: fileName,
      directory: Directory.Data
    });
    const fileOpener = new FileOpener();
    await fileOpener.open(fileUri.uri, data.type);
    console.log('File is opened');
  } catch (e) {
    console.error('Error handling file:', e);
  }
}

// 封装Blob转base64的Promise方法
private static blobToBase64(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

方案3:内存优化补充

  • 手动释放引用:文件操作完成后,将Blob对象置为null,帮助垃圾回收:
    data = null; // 释放Blob内存
    
  • 更换存储目录:尝试将文件写入Directory.Documents,部分平台对该目录的内存限制更宽松
  • 更新插件版本:确保@capacitor/filesystem和cordova-plugin-file-opener2是最新版本,新版本修复了不少内存泄漏问题

内容的提问来源于stack exchange,提问作者pilotman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 11:00:00