トップ › 技術ブログ › ファイルを送らない Web ツールの作り方
ファイルを送らない Web ツールの作り方 ― 手箱(Tebako)のブラウザ内処理と、その代償
この記事は、当社(Gratias合同会社)が開発・運営している無料ツール「手箱(Tebako)」について、開発チームが仕組みを解説するものです。自社のサービスの紹介を含みます。
手箱は、PDF の結合や墨消し、写真の位置情報の削除、録音の切り出しといった「ちょっとした直し」を、ファイルをアップロードせずに行う Web ツールです。一般的なオンラインツールは、ファイルをサーバに送って処理し、結果を送り返します。手箱は処理をすべて利用者のブラウザの中で行い、サーバは画面を作るためのファイルを配るだけです。
「送らない」と書くのは簡単ですが、実際に作ってみると、ブラウザの中だけで済ませるための工夫と、そのために諦めたことがいくつもありました。この記事では、手箱の中で何が動いているのかと、ブラウザ内処理の得失を、開発の記録をもとに紹介します。
ブラウザの中で、ファイルはどう扱われるか
利用者がファイルを選ぶかドラッグすると、ブラウザはそれを File(Blob)としてページに渡します。この時点ではまだどこにも送られていません。手箱はこの Blob を、ブラウザに備わった機能と、ページと一緒に配った JavaScript の部品(AI の処理では WebAssembly も)で読み解きます。
| ツール | 読み込み | 加工と書き出し |
|---|---|---|
| オーディオ | Web Audio API(decodeAudioData) | 自前の WAV 書き出し、MP3 は lamejs。Web Worker で実行 |
| pdf.js(表示と文字の位置の取得) | pdf-lib で新しい PDF を組み立てる | |
| イメージ | createImageBitmap・Canvas | メタデータの削除は自前のコード、縮小・拡大は自前の Lanczos を Worker で |
書き出した結果は、ブラウザの中で blob: で始まる一時的な URL になり、保存ボタンで端末に保存されます。開発者ツールのネットワーク欄にも blob: の行が出ますが、これは端末の中の参照で、通信ではありません。
重い部品は、使う場面になるまで読み込まないようにしています。たとえば MP3 の書き出し部品は MP3 を選んだときだけ、PDF を組み立てる pdf-lib は書き出すときだけ読み込みます。開くたびに全部を取りに行くと、最初の表示が遅くなるうえ、ネットワーク欄に「何に使うのか分からない通信」が並んでしまうからです。
サーバ側は「受け取らない」作りにする
ブラウザの中で処理する、というだけでは、利用者からは本当に送っていないのか分かりません。そこで手箱では、サーバの側にファイルを受け取る入り口そのものを置いていません。
- サーバは静的なファイル(HTML・JavaScript・CSS など)を配るだけで、アップロードを受け付ける処理を持たない
- 読み取り(GET と HEAD)以外のリクエストは 405 で断る
- リクエストの本文は 1KB までに制限する
公開後に、200KB のデータを POST で送りつけて 405 が返ることを確かめています。各ツールの説明ページには、同じことを利用者が自分で試せるコマンドを載せています。
ブラウザの側でも、読み込んで書き出すまでの通信を数えました。音声を読み込んで WAV で書き出す流れでは、画面を開いたときのファイルと blob: の行のほかに増えたのは、書き出し用の Worker の 1 件だけでした(MP3 を選ぶと MP3 の部品がもう 1 件)。画像では blob: が 2 件と縮小・拡大用の Worker が 1 件、PDF では pdf.js・その Worker・pdf-lib の 3 つだけで、どのツールも GET 以外の通信は 0 件でした。説明ページに「見えるはずのもの」を書いたら、その内容を実物で測って突き合わせる、という順番を守っています。
広告とブラウザ側の制限の関係
手箱は広告収入で運営しています。そのため、ページには Google の広告配信のスクリプトが入っています。ここは正直に書いておきたい点です。
当初は、CSP(Content-Security-Policy)でスクリプトの読み込み元を自社のサイトだけに絞り、「仮に作りに間違いがあってもブラウザが外への送信を止める」形を考えていました。しかし広告を置くには Google の配信元を許可する必要があり、Google はドメインを列挙する形の CSP を公式には支持していません。広告を載せた時点で、「自社のスクリプトしか動かない」という保証は手放しています。
そのうえで、私たちが約束しているのは次の 2 点です。手箱のサーバはファイルを受け取らないこと、手箱のコードはファイルを外へ送らないこと。広告のスクリプトは手箱のページの中で動くので、ページ上のデータに技術的に一切触れられない、とまでは言えません。その代わり、ツールの中で広告を置くのは、ファイルを読み込む前の画面と書き出しが終わった後の画面、それに AI の拡大処理を待つあいだの画面だけで、編集中の画面には出していません。
ブラウザ内処理で受け入れた制約
サーバに送らない作りには、利用者にもこちらにも利点があります。利用者はファイルを預けずに済み、こちらは利用者のファイルを預かる責任とサーバの計算資源を持たずに済みます。一方で、ブラウザの中だけで済ませることで生じた制約もはっきりあります。
1. 速さとメモリは利用者の端末次第
処理するのは利用者の端末なので、古い PC やスマートフォンでは遅くなり、メモリが足りなければブラウザのタブごと止まります。オーディオでは、元の音・編集後の音・試聴用の音を持つため、元の音声のおよそ 2.5 倍のメモリを使います。そこで読み込める長さに上限を設け、PC では 60 分、メモリ 4GB 以下と申告する端末では 30 分、タッチ操作の端末では 20 分としました。
編集の持ち方も、メモリを増やさない形にしています。削除や無音カットのたびに音のコピーを作るのではなく、「元の時間軸のどこを残すか」の一覧だけを持ち、元の音には最後まで手を付けません。
// 編集は「残す区間」の一覧で表す(単位は秒)
export function initialKeep(duration) {
return [{ start: 0, end: duration }]
}
元に戻す・やり直すはこの一覧の履歴を行き来するだけなので、何回操作しても音のコピーは積み上がりません。
2. ブラウザの機能の癖をそのまま受ける
読み込める形式はブラウザによって変わります。WAV・MP3 はどこでも読めますが、OGG や FLAC は環境次第で、WMA は読めません。サーバに変換ソフトを置けば解決しますが、それは「送らない」前提に反します。
見えにくい癖もありました。Web Audio API の decodeAudioData は、読み込んだ音をブラウザの既定の標本化周波数に黙って変換します。実際に 22,050Hz の WAV が 44,100Hz になって返ってきました。手箱ではファイルの先頭から元の周波数を読み、その値で処理の器を作ることで、元の周波数のまま書き出すようにしています。また、この AudioContext は Web Worker の中では使えないため、読み込みだけは画面のスレッドで行い、重い書き出しを Worker に回しています。
3. 作業内容はどこにも残らない
サーバに保存しないので、ページを閉じれば編集中の内容は消えます。手箱は cookie も localStorage も使っていないため、「続きから」の機能もありません。
4. 賢い処理ほど、端末に持ち込むものが増える
サーバなら大きな AI モデルで済むことも、ブラウザの中では端末に取り寄せる必要があります。PDF の「個人情報を探す」では、モデルを使わずに正規表現で候補を探しています。追加の取得が要らず、なぜそこが選ばれたかを説明でき、何度やっても同じ結果になるからです。その代わり、決まった形をしていない情報は見逃します。開発時の試験では、日本語の見積書で 10 種類の項目を拾えた一方、住所の末尾の番地は外れました。候補はあくまで候補で、最後は人の目で確かめていただく設計にしています。
画像の AI 超解像度処理は、AI モデルを端末に取り寄せ、GPU で動かしています。初回だけ処理用のプログラムと AI モデルで約 22〜24MB の取得が発生し、WebGPU に対応した環境が必要です。こちらの仕組みは別の記事で詳しく紹介しています。
5. 「本当に消えたか」は自分たちで測る
PDF の墨消しは、黒い四角を上に重ねるだけでは下の文字が残ります。手箱では、墨消しするページをいったん画像として描き直してから塗りつぶし、ページごと置き換えています。そのページは文字の選択や検索ができなくなりますが、元の文字は書き出したファイルに含まれません。試験用の文字列を入れた PDF を墨消しして書き出し、文字を取り出す別のツールで調べて、その文字列が出てこないことを確かめています。
写真のメタデータの削除では逆に、絵には触らずにメタデータの部分だけを外しています。試験では、JPEG から Exif の 242 バイトだけが減り、画像本体の圧縮データ(57,118 バイト)はハッシュ値まで一致しました。ブラウザの中で処理するからこそ、こうした結果を自分たちで数字にして確かめることを大事にしています。
まとめ
手箱の「送らない」は、ブラウザの中で処理する作りと、サーバに受け口を置かない作りの二つで支えています。一方で、速さとメモリは端末次第で、形式の対応はブラウザ次第、作業内容は残らず、広告を載せる以上ブラウザ側の制限には限りがあります。
こうした得失を隠さずに説明し、書いたことは実物で測って確かめる。手箱ではそれを開発の決まりにしています。「アップロードしたくないファイルがある」ときの選択肢として、お役に立てば幸いです。
手箱(Tebako)
PDF の結合・分割・墨消し、写真の位置情報の削除や AI 超解像度処理、音声の切り出しと無音カットを、ファイルをアップロードせずにブラウザの中で行える無料ツールです。登録は要りません。
手箱を開く