Skip to main content
LadeStack LogoLadeStack
Tools 約 9 分 2026年3月18日

クライアントサイドPDF処理:WebAssemblyによるメモリ内データ操作

サーバーへのファイル送信を一切行わず、ブラウザのRAM上でWebAssemblyとUint8Arrayバッファを用いてPDFの結合・分割・最適化を完結させる独自アーキテクチャを解説。

クライアントサイドPDFエンジン アーキテクチャ図

従来のドキュメント処理システムでは、PopplerやGhostscript、PDFKitなどのネイティブバイナリを稼働させたバックエンドのマイクロサービスが中心的な役割を担ってきました。機密性の高い請求書を結合したり、個人医療記録から特定ページを抽出したりする場合、標準的なWebツールではファイル全体をインターネット経由でリモートクラウドへアップロードする必要がありました。

企業環境、法務契約書、プライバシーに関わる記録において、暗号化されていないドキュメントストリームを外部クラウド基盤へ中継することは、攻撃対象領域を広げ、GDPRの国境を越えたデータ移転評価やCCPAの事業者責任などのコンプライアンス管理を複雑化させます。

LadeStackの開発者ユーティリティスイートの一環であるLS PDFの開発において、私たちは完全なクライアントサイド型のドキュメント処理パイプラインを構築しました。ブラウザ内のUint8Arrayバッファ上で直接WebAssembly(Wasm)エンジンを実行することにより、外部サーバーへファイルデータを送信することなく、ドキュメントの変換処理をローカルRAM内で完結させています。


ゼロアップロード・プライバシーモデル

機密文書を扱うにあたり、最も確実なプライバシー保証はアーキテクチャそのものにあります。**「受信しないデータをサーバーが漏洩させることはできない」**という原則です。

従来のクラウドPDFツール:
[ブラウザ ファイル選択] ──(大容量アップロード)──► [クラウドサーバー/DB] ──► [ディスク書き込み] ──► [処理] ──► [ダウンロード]

LADESTACK LS PDF (WASM):
[ブラウザ ファイル選択] ──► [ローカルRAM上のArrayBuffer] ──► [WASM実行エンジン] ──► [即座にローカル保存]
                                     ▲
                                     └─── ファイル本文のネットワーク通信量: 0バイト

ファイルを端末ローカルに留めることで、以下のような決定的な利点が生まれます。

  • ネットワーク転送遅延の完全排除: 150 MB規模の大容量ドキュメントであっても、処理時間は端末のCPUとRAM性能のみに依存し、モバイル回線の遅い上り速度に縛られません。
  • データ露出リスクの大幅な低減: ファイル本体が外部エンドポイントやクラウドストレージを通過しないため、サードパーティ基盤でのデータ保持リスクを抑制できます(ただし組織全体の包括的なコンプライアンスには端末セキュリティや社内ガバナンス体制が必要です)。
  • オフラインでの処理実行: Webアプリケーション資産とWASMモジュールがブラウザにキャッシュされれば、インターネット接続がない環境でもPDFの変換・抽出処理を確実に実行できます。

メモリ内バイナリ操作:ArrayBufferパイプライン

最新のWebブラウザは、W3Cの標準仕様であるFileReaderおよびBlob APIを通じて、ローカルファイルを直接バイトストリームとして読み取る機能を提供しています。LS PDFでは、これらのAPIをTypedArrayと連携させて処理を行います。

/**
 * ユーザーが選択したローカルファイルをメモリ内のUint8Arrayとして読み込む
 */
export async function readFileAsBinary(file: File): Promise<Uint8Array> {
  const arrayBuffer = await file.arrayBuffer();
  return new Uint8Array(arrayBuffer);
}

メモリ上にバイト配列が展開されると、共有メモリポインタを介してWebAssemblyのリニアメモリ境界へ直接データが受け渡されます。

WebAssemblyメモリのマーシャリング

ブラウザ内でC++やRustによる高速パース処理を実行するため、JavaScriptホスト環境はWebAssemblyインスタンス内のリニアメモリ領域を割り当てます。

// WebAssemblyメモリ空間内にバッファを確保
const fileData = await readFileAsBinary(uploadedFile);
const wasmMemory = wasmInstance.exports.memory as WebAssembly.Memory;

// WASM内のアロケータへメモリ確保を要求
const ptr = wasmInstance.exports.allocate_buffer(fileData.length);
const memoryView = new Uint8Array(wasmMemory.buffer, ptr, fileData.length);

// ローカルのバイトデータをWASMメモリへコピー
memoryView.set(fileData);

// コアのドキュメント変換処理を実行(結合、回転、ページ並べ替え)
const resultPtr = wasmInstance.exports.process_pdf(ptr, fileData.length);

JSONやBase64へのエンコード変換を挟まず、リニアメモリオフセットを直接操作することにより、ネイティブバイナリに迫る高速な処理速度を実現しています。


メモリ管理とクラッシュ防止の安全策

大容量のPDFドキュメントをブラウザのメモリ内で処理する際は、厳格なメモリライフサイクル管理が不可欠です。標準的な32ビットWebAssembly(wasm32)は32ビットのリニアアドレス空間で動作するため、理論上の上限は4 GB($2^{32}$バイト)です。実際のブラウザエンジン(ChromiumのV8など)では、タブ全体の安定性を保つため、単一のWASMインスタンスに対して1 GB〜2 GB程度のヒープ上限を設けているのが一般的です。確保したメモリを明示的に解放しない場合、連続したドキュメント操作によってメモリ不足(Out-Of-Memory)によるタブ強制終了が発生します。

明示的なポインタ解放処理

WebAssemblyのリニアメモリには自動ガベージコレクション機構が存在しません。そのため、確保したすべてのメモリバッファはJavaScript側から明示的に破棄する必要があります。

try {
  const processedLength = wasmInstance.exports.get_result_length();
  const processedBytes = new Uint8Array(
    wasmMemory.buffer,
    resultPtr,
    processedLength
  ).slice(); // JavaScript管理メモリへクローンして保存

  return new Blob([processedBytes], { type: 'application/pdf' });
} finally {
  // WASMヒープバッファを明示的に解放
  wasmInstance.exports.deallocate_buffer(ptr, fileData.length);
  wasmInstance.exports.deallocate_buffer(resultPtr, processedLength);
}

処理結果を標準のJavaScript Blobへクローンした直後に、基盤となるWebAssemblyヒープバッファを解放することで、メモリ消費の急激なスパイクを瞬時に解消します。


ネットワーク転送とローカル実行:理論的遅延モデルの比較

クライアント側ドキュメント処理を評価する際、最も本質的な優位性はネットワーク転送フェーズの完全な排除にあります。従来のクラウドワークフローでは、大容量ドキュメントのアップロードとダウンロードに伴う伝送遅延が不可避です。

伝送遅延の計算モデル

ネットワーク伝送時間は、データ通信の基本原理に基づき定義されます:

$\text{伝送遅延 } (T) = \frac{\text{データサイズ } (L)}{\text{実効帯域幅 } (R)}$

45 MB(360メガビット)の複数ドキュメント結合処理を、15 Mbpsのモバイル上り回線で試算した場合:

$\text{アップロード伝送遅延} = \frac{360\text{ Mb}}{15\text{ Mbps}} = 24.0\text{ 秒}$

処理後のダウンロード容量が約11.25 MB(90メガビット)と仮定すると、下り転送にさらに $6.0\text{ 秒}$ を要し、リモートサーバーの処理待ち時間を除いても30.0秒のネットワーク伝送遅延が発生します。

アーキテクチャ比較

実行モデル ネットワーク伝送遅延(15 Mbps試算) 実行境界 主なボトルネック
リモートクラウド処理 計 ~30.0秒(上り ~24.0秒 + 下り ~6.0秒) リモートキューおよびクラウドストレージ 上り無線帯域幅およびサーバー待機キュー
ローカルWASM処理 0.0秒(ペイロード転送なし) ブラウザ内メモリ(ArrayBuffer) クライアントCPU演算速度およびメモリ帯域

方法論上の注記: クラウド転送の数値はデータ容量と帯域幅から算出した理論伝送遅延($T = L / R$)であり、実測所要時間ではありません。ローカルWASM実行の実際の所要時間は、端末CPU性能やPDF内部構造(ベクター、フォント、圧縮ストリーム)の複雑度に依存します。ネットワーク伝送がゼロであることを示しつつ、任意の固定処理時間を断定するものではありません。


LadeStack製品への適用と今後の展開

このクライアント完結型アーキテクチャは、LadeStackのエコシステム全体を支える基盤技術です。

  • LS PDF 結合ツール: クラウドに一切保存することなく、複数の契約書を1つのファイルに統合。
  • LS PDF ページ分割ツール: 必要なページ範囲だけを抽出してローカルに即座保存。
  • クライアントサイド最適化: 内部ストリームオブジェクトの再エンコードによるファイルサイズ削減。

プライバシーを最優先に設計された開発者ツールの詳細は、LadeStack アプリディレクトリまたはプライバシーポリシーにてご確認いただけます。