mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-04-12 19:58:29 +00:00
48 lines
2.1 KiB
Markdown
48 lines
2.1 KiB
Markdown
---
|
||
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)を参照してください。
|