---
title: "C09. チャンク転送でボディを送る"
order: 9
status: "draft"
---

送信するボディのサイズが事前にわからないとき、たとえばリアルタイムに生成されるデータや別のストリームから流し込むデータを送りたいときは、`ContentProviderWithoutLength`を使います。HTTPのチャンク転送エンコーディング（chunked transfer-encoding）として送信されます。

## 基本の使い方

```cpp
httplib::Client cli("http://localhost:8080");

auto res = cli.Post("/stream",
  [&](size_t offset, httplib::DataSink &sink) {
    std::string chunk = produce_next_chunk();
    if (chunk.empty()) {
      sink.done(); // 送信終了
      return true;
    }
    return sink.write(chunk.data(), chunk.size());
  },
  "application/octet-stream");
```

ラムダは「次のチャンクを作って`sink.write()`で送る」だけです。データがもう無くなったら`sink.done()`を呼べば送信が完了します。

## サイズがわかっている場合

送信するボディの**合計サイズが事前にわかっている**ときは、`ContentProvider`（`size_t offset, size_t length, DataSink &sink`を取るタイプ）と合計サイズを渡す別のオーバーロードを使います。

```cpp
size_t total_size = get_total_size();

auto res = cli.Post("/upload", total_size,
  [&](size_t offset, size_t length, httplib::DataSink &sink) {
    auto data = read_range(offset, length);
    return sink.write(data.data(), data.size());
  },
  "application/octet-stream");
```

サイズがわかっているとContent-Lengthヘッダーが付くので、サーバー側で進捗を把握しやすくなります。可能ならこちらを使いましょう。

> **Detail:** `sink.write()`は書き込みが成功したかどうかを`bool`で返します。`false`が返ったら回線が切れています。ラムダはそのまま`false`を返して終了しましょう。

> ファイルをそのまま送るだけなら、`make_file_body()`が便利です。[C08. ファイルを生バイナリとしてPOSTする](../c08-post-file-body)を参照してください。
