「ZIP ってストリーミングできるんだ」とpCloud を使って気づいた話

パソコン技術の小ネタ

クラウドストレージの pCloud を使っていて、前からちょっと気になっていたことがある。
1GB くらいのファイルをブラウザからダウンロードすると、
ZIP の準備がほぼ一瞬で終わるんだよね。
普通なら ZIP を作るのに時間がかかるはずなのに、
pCloud は「はい ZIP できました、どうぞ〜」みたいな感じで即ダウンロードが始まる。
「いやいや、1GB を一瞬で圧縮なんて無理でしょ」と思って調べてみたら、
どうやら ZIP の仕様そのものが“ストリーミング向き”だったという意外な事実にたどり着いた。

pCloud は ZIP を“作ってから送っている”わけじゃなかった

調べてみると、pCloud の ZIP ダウンロードはこんな仕組みらしい。
ZIP を事前に作って保存しているわけではない
ZIP を作りながら、そのままブラウザへ流している(ストリーミング)
圧縮はほぼ無圧縮(Store モード)
最後に ZIP の「目次」だけ付け足して完成
つまり、
「ZIP を作りながら送る」から、圧縮が一瞬に見える
ということだった。

ZIP は「全部作ってからじゃないと壊れる」と思っていた

正直、ZIP ってこういう流れだと思っていた。
全ファイルを読み込む
圧縮する
ZIP を完成させる
それから送る
実際、普通の ZIP ソフトはこの方式だから、
pCloud の挙動が不思議に見えたのも当然。

実は ZIP は“後からヘッダを書ける”柔軟なフォーマットだった

ZIP の仕様には data descriptor という仕組みがあって、
これがとても便利。
ファイルサイズ
CRC(チェックサム)
これらを データを書いた後に追記してもいい という仕様になっている。
つまり ZIP は、
データ本体を先に全部流して、後から必要情報を付け足せる
という、実はとても柔軟なフォーマットだった。
さらに ZIP の「中央ディレクトリ(目次)」はファイルの最後にあるので、
本体をストリーミングで送りつつ、最後に目次を付ければ ZIP として成立する
というわけ。

ZIP がストリーミングに向いているのは“偶然の産物”?

ZIP が作られたのは 1989 年。
当時はストリーミングなんて一般的じゃなかった。
なのに、
後書き可能なヘッダ
最後に目次
無圧縮モード
柔軟な構造
こういう特徴が組み合わさって、
クラウド時代に「ストリーミング生成に最適なフォーマット」として再評価された。
まさに「結果的にそうなった」って感じ。

PHP でも pCloud と同じことができる…らしい?

自分では作ってないけど、
さらに調べていくうちに、
どうやら PHP でもストリーミング ZIP を作れる方法があるらしい、という情報に行き当たった。
ただし、ちょっと注意点もあるみたい。
✖ 標準の ZipArchive はストリーミングには向いていないらしい
どうも PHP に最初から入っている ZipArchive は、
一時ファイルを作る必要がある
ZIP を全部作り終わってからじゃないと送れない
という仕組みらしく、
pCloud みたいな「作りながら送る」方式には向いていないっぽい。
✔ ストリーミング ZIP を作れるライブラリもあるらしい
一方で、ネットを見ていると
ZipStreamWriter(php-zipstreamwriter) みたいなライブラリがあって、
ディスクに ZIP を作らず
データを読みながら ZIP を生成して
data descriptor を使って後から CRC やサイズを追記して
最後に中央ディレクトリを書いて ZIP を完成させる
…という、まさにストリーミング向けの作りになっているらしい。
しかも Zip64 にも対応していて、
大きなファイルでも扱えるとのこと。
つまりまとめると、
PHP でも「作りながら送る ZIP」が実現できるらしい
という感じ。

まとめ:ZIP は思った以上に“ストリーミング向き”だった

pCloud の挙動から始まった疑問は、
ZIP の意外な柔軟性にたどり着いた。
ZIP は後からヘッダを書ける
目次は最後に書く
無圧縮ならデータをそのまま流せる
だからストリーミング生成が可能
pCloud はこれを最大限活用している
PHP でも同じことができる…らしい
ZIP は古いフォーマットだけど、
実はクラウド時代にもバッチリ通用する“強い仕様”でビックリした。