圧縮

現行標準 — 最終更新

参加方法:
GitHub whatwg/compression (新しいissue, オープン中のissue)
Matrixでチャット
コミット:
GitHub whatwg/compression/commits
このコミット時点のスナップショット
@compressionapi
テスト:
web-platform-tests compression/ (進行中の作業)
翻訳 (参考訳):
简体中文
日本語
한국어

概要

この文書は、バイナリデータのストリームを圧縮および展開するためのJavaScript APIのセットを定義します。

1. はじめに

この節は参考情報です。

本仕様で定義されているAPIは、データストリームの圧縮および展開に使用されます。"deflate"、"deflate-raw"、"gzip"の各圧縮アルゴリズムをサポートしており、Web開発者に広く利用されています。

2. インフラストラクチャー

本仕様はInfraに依存しています。[INFRA]

チャンクとはデータの断片です。CompressionStreamおよびDecompressionStreamの場合、出力チャンクの型はUint8Arrayです。入力としては、任意のBufferSource 型を受け付けます。

ストリームは、順序付けられたチャンクの列を表します。ReadableStream およびWritableStream という用語はStreamsで定義されています。[STREAMS]

圧縮コンテキストとは、圧縮または展開アルゴリズムによって管理される内部状態のことです。圧縮コンテキストの内容は、使用するフォーマット・アルゴリズム・実装によって異なります。本仕様の観点からは、不透明なオブジェクトです。圧縮コンテキストは、最初は入力の最初のバイトを待ち受ける開始状態です。

3. 対応フォーマット

deflate

"ZLIB圧縮データフォーマット"[RFC1950]

注: このフォーマットは、HTTP Content-Encodingとの一貫性のために「deflate」と呼ばれます。[RFC7230] セクション4.2.2を参照してください。

  • 実装は[RFC1950] セクション2.3で述べられている「適合」要件を満たさなければなりません。

  • [RFC1950]で無効とされるフィールド値はCompressionStreamにより生成してはならず、DecompressionStreamではエラーとなります。

  • CMFフィールドのCM(圧縮方式)部分の唯一の有効な値は8です。

  • FDICTフラグはこれらのAPIでサポートされず、設定されている場合はストリームがエラーになります。

  • FLEVELフラグはDecompressionStreamで無視されます。

  • ADLER32チェックサムが正しくない場合、DecompressionStreamではエラーとなります。

  • ADLER32チェックサムの後に追加の入力データがある場合はエラーとなります。

deflate-raw

"DEFLATEアルゴリズム"[RFC1951]

  • 実装は[RFC1951] セクション1.4で述べられている「適合」要件を満たさなければなりません。

  • [RFC1951]に準拠しないブロックはCompressionStreamで生成してはならず、DecompressionStreamではエラーとなります。

  • BFINALフラグで示される最終ブロックの後に追加の入力データがある場合はエラーとなります。

gzip

"GZIPファイルフォーマット"[RFC1952]

  • 実装は[RFC1952] セクション2.3.1.2で述べられている「適合」要件を満たさなければなりません。

  • [RFC1952]で無効とされるフィールド値はCompressionStreamにより生成してはならず、DecompressionStreamではエラーとなります。

  • CM(圧縮方式)フィールドの唯一の有効な値は8です。

  • FTEXTフラグはDecompressionStreamで無視されなければなりません。

  • FHCRCフィールドが存在する場合、それが正しくないとエラーになります。

  • 任意のFEXTRAFNAMEFCOMMENTフィールドの内容は、DecompressionStreamでは正しく終端されているかどうかの検証以外は無視されなければなりません。

  • MTIMEXFLOSフィールドの内容はDecompressionStreamで無視されなければなりません。

  • CRC32またはISIZEが展開後のデータと一致しない場合はエラーとなります。

  • gzipストリームは1つの「メンバー」のみを含む必要があります。

  • 「メンバー」の終了後に追加の入力データがある場合はエラーとなります。

4. インターフェース CompressionStream

enum CompressionFormat {
  "deflate",
  "deflate-raw",
  "gzip",
};

[Exposed=*]
interface CompressionStream {
  constructor(CompressionFormat format);
};
CompressionStream includes GenericTransformStream;

CompressionStream には、関連付けられたformat(フォーマット)および圧縮コンテキストとしてのcontext(コンテキスト)がある。

new CompressionStream(format) の手順は以下の通り:
  1. formatCompressionStream でサポートされていない場合、TypeErrorをスローする。

  2. thisformatformatに設定する。

  3. transformAlgorithmを、chunk引数を受け取り、チャンクを圧縮してエンキューするアルゴリズムをthischunkで実行するアルゴリズムとする。

  4. flushAlgorithmを、引数を取らず圧縮フラッシュしてエンキューするアルゴリズムをthisで実行するアルゴリズムとする。

  5. thistransform新しいTransformStreamに設定する。

  6. thisのtransformをセットアップし、transformAlgorithmtransformAlgorithmを、flushAlgorithmflushAlgorithmを設定する。

チャンクを圧縮してエンキューするアルゴリズムは、CompressionStream オブジェクトcschunkを受け、以下の手順を実行する:
  1. chunkBufferSource 型でない場合、TypeErrorをスローする。

  2. bufferに、csformatおよびcontextchunkを圧縮した結果を格納する。

  3. bufferが空なら、return する。

  4. arraysに、bufferを1つ以上の非空部分に分割し、それぞれをUint8Arrayに変換した結果を格納する。

  5. 配列ごとにUint8Array arrayについて、csのtransformにarrayをエンキューする。

圧縮フラッシュしてエンキューするアルゴリズムは、入力ReadableStream オブジェクトの終端時に、CompressionStream オブジェクトcsに対して、以下の手順を実行する:
  1. bufferに、csformatおよびcontextで、finishフラグ付きで空入力を圧縮した結果を格納する。

  2. bufferが空なら、return する。

  3. arraysに、bufferを1つ以上の非空部分に分割し、それぞれをUint8Arrayに変換した結果を格納する。

  4. 配列ごとにUint8Array arrayについて、csのtransformにarrayをエンキューする。

5. インターフェース DecompressionStream

[Exposed=*]
interface DecompressionStream {
  constructor(CompressionFormat format);
};
DecompressionStream includes GenericTransformStream;

DecompressionStream には、関連付けられたformat(フォーマット)および圧縮コンテキストとしてのcontext(コンテキスト)がある。

new DecompressionStream(format) の手順は以下の通り:
  1. formatDecompressionStream でサポートされていない場合、TypeErrorをスローする。

  2. thisformatformatに設定する。

  3. transformAlgorithmを、chunk引数を受け取り、チャンクを展開してエンキューするアルゴリズムをthischunkで実行するアルゴリズムとする。

  4. flushAlgorithmを、引数を取らず展開フラッシュしてエンキューするアルゴリズムをthisで実行するアルゴリズムとする。

  5. thistransform新しいTransformStreamに設定する。

  6. thisのtransformをセットアップし、transformAlgorithmtransformAlgorithmを、flushAlgorithmflushAlgorithmを設定する。

チャンクを展開してエンキューするアルゴリズムは、DecompressionStream オブジェクトdschunkを受け、以下の手順を実行する:
  1. chunkBufferSource 型でない場合、TypeError をスローする。

  2. buffer を、dsformat および contextchunk を解凍した結果とする。この処理でエラーが発生した場合、TypeError をスローする。

  3. buffer が空の場合は、return する。

  4. arraysbuffer を1つ以上の非空の部分に分割し、それらを Uint8Array に変換した結果とする。

  5. Uint8Array arrayarrays から取り出し、enqueuearraydstransform に追加する。

  6. 圧縮入力の終端に到達し、かつ dscontextchunk を完全に消費していない場合、TypeError をスローする。

展開フラッシュしてエンキューするアルゴリズムは、入力ReadableStream オブジェクトの終端時に、DecompressionStream オブジェクトdsに対して、以下の手順を実行する:
  1. buffer を、空の入力を dsformat および context で、finish フラグ付きで解凍した結果とする。

  2. buffer が空でない場合:

    1. arraysbuffer を1つ以上の非空の部分に分割し、それらを Uint8Array に変換した結果とする。

    2. Uint8Array arrayarrays から取り出し、enqueuearraydstransform に追加する。

  3. 圧縮入力の終端に到達していない場合は、TypeError をスローする。

6. プライバシーおよびセキュリティの考慮事項

このAPIはWebプラットフォームに新たな権限を追加しません。

ただし、攻撃者がデータの長さを取得できる場合、Web開発者は注意する必要があります。その場合、データの内容を推測される可能性があります。

7.

7.1. ストリームをGzip圧縮する

const compressedReadableStream
    = inputReadableStream.pipeThrough(new CompressionStream('gzip'));

7.2. ArrayBufferをDeflate圧縮してUint8Arrayに変換

async function compressArrayBuffer(input) {
  const cs = new CompressionStream('deflate');

  const writer = cs.writable.getWriter();
  writer.write(input);
  writer.close();

  const output = [];
  let totalSize = 0;
  for (const chunk of cs.readable) {
    output.push(value);
    totalSize += value.byteLength;
  }

  const concatenated = new Uint8Array(totalSize);
  let offset = 0;
  for (const array of output) {
    concatenated.set(array, offset);
    offset += array.byteLength;
  }

  return concatenated;
}

7.3. BlobをGzip展開してBlobに変換

function decompressBlob(blob) {
  const ds = new DecompressionStream('gzip');
  const decompressionStream = blob.stream().pipeThrough(ds);
  return new Response(decompressionStream).blob();
}

謝辞

Canon Mukai、Domenic Denicola、そして平野豊に感謝します。

この標準はAdam Rice(Googlericea@chromium.org)によって執筆されました。

知的財産権

この現行標準はもともとW3C WICGで開発され、W3Cソフトウェアおよびドキュメントライセンスの下で公開されていました。

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). この作業はクリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下で提供されます。その一部がソースコードに組み込まれている場合、ソースコード部分は代わりにBSD 3-Clause Licenseの下でライセンスされます。

これは現行標準です。 特許審査バージョンに関心のある方は、 現行標準審査ドラフトを参照してください。

索引

本仕様で定義されている用語

他仕様で定義されている用語

参考文献

規範的参考文献

[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. 現行標準. URL: https://infra.spec.whatwg.org/
[RFC1950]
P. Deutsch; J-L. Gailly. ZLIB Compressed Data Format Specification version 3.3. 1996年5月. Informational. URL: https://www.rfc-editor.org/rfc/rfc1950
[RFC1951]
P. Deutsch. DEFLATE Compressed Data Format Specification version 1.3. 1996年5月. Informational. URL: https://www.rfc-editor.org/rfc/rfc1951
[RFC1952]
P. Deutsch. GZIP file format specification version 4.3. 1996年5月. Informational. URL: https://www.rfc-editor.org/rfc/rfc1952
[STREAMS]
Adam Rice ほか. Streams Standard. 現行標準. URL: https://streams.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. 現行標準. URL: https://webidl.spec.whatwg.org/

参考情報

[RFC7230]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing. 2014年6月. Proposed Standard. URL: https://httpwg.org/specs/rfc7230.html

IDL索引

enum CompressionFormat {
  "deflate",
  "deflate-raw",
  "gzip",
};

[Exposed=*]
interface CompressionStream {
  constructor(CompressionFormat format);
};
CompressionStream includes GenericTransformStream;

[Exposed=*]
interface DecompressionStream {
  constructor(CompressionFormat format);
};
DecompressionStream includes GenericTransformStream;

MDN

CompressionStream/CompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js17.0.0+
MDN

CompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

DecompressionStream/DecompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js17.0.0+
MDN

DecompressionStream

In all current engines.

Firefox113+Safari16.4+Chrome80+
Opera?Edge80+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+