Files
cpp-httplib/docs-src/pages/ja/cookbook/s07-multipart-reader.md
2026-04-11 20:40:08 -04:00

72 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "S07. マルチパートデータをストリーミングで受け取る"
order: 26
status: "draft"
---
大きなファイルをアップロードするハンドラを普通に書くと、`req.body`にリクエスト全体が載ってしまいメモリを圧迫します。`HandlerWithContentReader`を使うと、ボディをチャンクごとに受け取れます。
## 基本の使い方
```cpp
svr.Post("/upload",
[](const httplib::Request &req, httplib::Response &res,
const httplib::ContentReader &content_reader) {
if (req.is_multipart_form_data()) {
content_reader(
// 各パートのヘッダー
[&](const httplib::FormData &file) {
std::cout << "name: " << file.name
<< ", filename: " << file.filename << std::endl;
return true;
},
// 各パートのボディ(複数回呼ばれる)
[&](const char *data, size_t len) {
// ここでファイルに書き出すなど
return true;
});
} else {
// 普通のリクエストボディ
content_reader([&](const char *data, size_t len) {
return true;
});
}
res.set_content("ok", "text/plain");
});
```
`content_reader`は2通りの呼び方ができます。マルチパートのときは2つのコールバックヘッダー用とデータ用を渡し、そうでないときは1つのコールバックだけを渡します。
## ファイルに直接書き出す
大きなファイルをそのままディスクに書き出す例です。
```cpp
svr.Post("/upload",
[](const httplib::Request &req, httplib::Response &res,
const httplib::ContentReader &content_reader) {
std::ofstream ofs;
content_reader(
[&](const httplib::FormData &file) {
if (!file.filename.empty()) {
ofs.open("uploads/" + file.filename, std::ios::binary);
}
return static_cast<bool>(ofs);
},
[&](const char *data, size_t len) {
ofs.write(data, len);
return static_cast<bool>(ofs);
});
res.set_content("uploaded", "text/plain");
});
```
メモリには常に小さなチャンクしか載らないので、ギガバイト級のファイルでも扱えます。
> **Warning:** `HandlerWithContentReader`を使うと、`req.body`は**空のまま**です。ボディはコールバック内で自分で処理してください。
> クライアント側でマルチパートを送る方法は[C07. ファイルをマルチパートフォームとしてアップロードする](c07-multipart-upload)を参照してください。