Den Overhead von multipart/form-data genau berechnen
Haben Sie schon die Erfahrung gemacht, dass 「die Datei 9MB groß ist, aber der Fehler 413 auftritt」 bei Größenlimit-Tests für Uploads? Eine der Ursachen ist der Overhead von <code>multipart/form-data</code>. Beim Hochladen einer Datei über ein HTML-Formular enthält der HTTP-Request-Body nicht nur die Datei selbst, sondern auch zusätzliche Metadaten. Dieser Artikel erklärt die präzise Berechnungsmethode dieses Overheads und wichtige Punkte beim Testen.
Struktur von multipart/form-data
Das in RFC 2046 definierte <code>multipart/form-data</code> hat eine Struktur, in der jeder Teil durch eine Boundary-Zeichenkette getrennt ist. Der tatsächliche HTTP-Request-Body sieht so aus.
POST /upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
Content-Length: 10000xyz
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="file"; filename="test.png"
Content-Type: image/png
[ファイルのバイナリデータ]
------WebKitFormBoundaryABC123--
Aufschlüsselung des Overheads
Der Overhead einer typischen Datei-Upload-Anfrage setzt sich aus den folgenden Elementen zusammen.
| Element | Beispiel | Anzahl der Bytes (Richtwert) |
|---|---|---|
| Anfang boundary | ------WebKitFormBoundaryABC123\r\n | Ungefähr 40–80 B |
| Content-Disposition-Header | Content-Disposition: form-data; name="file"; filename="test.png"\r\n | Ungefähr 60–120 B |
| Content-Type-Header | Content-Type: image/png\r\n | Ungefähr 25–50 B |
| Leerzeile (Ende des Headers) | \r\n | 2 B |
| Zeilenumbruch am Ende des Teils | \r\n | 2 B |
| End-Grenzmarke | ------WebKitFormBoundaryABC123--\r\n | Ungefähr 42–82 B |
| <strong>Gesamter Overhead</strong> | <strong>Etwa 200–350 B</strong> |
Bei einem einfachen Formular mit nur einer Datei beträgt der Overhead etwa <strong>200–400 Bytes</strong>. Falls zusätzliche Formularfelder (wie Texteingaben) vorhanden sind, erhöht sich dieser Wert entsprechend, bleibt aber in der Regel im Bereich von einigen hundert Bytes bis zu einigen KB.
Warum tritt der Fehler 413 auf
Das <code>client_max_body_size</code> von Nginx begrenzt die Größe des <strong>gesamten Request-Body</strong>. Das heißt, der konfigurierte Wert muss Overhead einschließen.
# 10MiB のファイルをアップロードさせたい場合
# オーバーヘッド(約1KB)を考慮して少し大きめに設定
client_max_body_size 11m; # MiB単位: 11 MiB = 11,534,336 バイト
In PHP müssen Sie zwei Werte konfigurieren: <code>upload_max_filesize</code> (einzelne Datei) und <code>post_max_size</code> (gesamter POST-Body).
; php.ini
upload_max_filesize = 10M ; ファイル単体の上限: 10 MiB
post_max_size = 11M ; POSTボディ全体の上限: 11 MiB(オーバーヘッド分を加算)
Methode zur Messung des genauen Overhead
Wenn Sie den tatsächlichen Overhead genau kennen möchten, können Sie mit curl Anfragen senden und die Anfragegröße messen.
# ファイルのバイト数を確認
wc -c test-10mb.png
# → 10485760 test-10mb.png
# curl でアップロードしてリクエストサイズを確認
curl -X POST https://example.com/upload \
-F "file=@test-10mb.png" \
-w "リクエストボディサイズ: %{size_upload} バイト\n" \
-o /dev/null -s
# → リクエストボディサイズ: 10486062 バイト(差: 302バイト)
Unterschiede zur Base64-Codierung
Bei <code>multipart/form-data</code> werden die Binärdaten der Datei unverändert übertragen (ohne Base64-Codierung). Base64-Codierung ist erforderlich, wenn Binärdaten mit <code>application/x-www-form-urlencoded</code> gesendet werden oder wenn Dateien im JSON-Body gesendet werden (<code>data:image/png;base64,...</code>).
| Übertragungsmethode | Overhead | Verwendung |
|---|---|---|
| multipart/form-data (HTML-Formular) | Hunderte B bis wenige KB | Normaler Datei-Upload |
| JSON + Base64 | Erhöhung um etwa 33% | Dateiübertragung über API |
| application/octet-stream(PUT) | Nahezu Null | S3 presigned URLs und ähnliches |
Wichtige Testpunkte
- Bestimmen Sie, ob die Limits-Überprüfung des Servers 「einzelne Datei」 oder 「gesamter Request-Body」 ist
- Da Nginx Anfragen vor PHP begrenzt, überprüfen Sie auch Nginx <code>client_max_body_size</code>
- Das gleichzeitige Hochladen mehrerer Dateien erhöht den Overhead
- Der Overhead umfasst auch zusätzliche Formularfelder (Name, Kommentare usw.)
Mit den <a href="/ja/files/threshold/">Grenzwert-Testdateien</a> von DevLab können Sie das tatsächliche Upload-Verhalten bei Dateigröße nahe der Grenzen überprüfen. Validieren Sie zusammen mit der Konfiguration von Nginx/Apache/PHP.
Zusammenfassung
- Der Overhead von <code>multipart/form-data</code> beträgt etwa <strong>200–400 Bytes</strong> (für eine Datei)
- Da <code>client_max_body_size</code> von Nginx den gesamten Request-Body begrenzt, sollte der Wert etwas größer als das Dateilimit sein
- PHP erfordert die Konfiguration von zwei Parametern: <code>upload_max_filesize</code> (einzelne Datei) und <code>post_max_size</code> (gesamter POST-Body)
- Beim Versand mit JSON + Base64 nimmt die Dateigröße um etwa 33% zu
Testdatei zur Verwendung in diesem Artikel
- → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">Liste von Schwellwert-Testdateien (9.9MB / 10MB / 10.1MB)</a>
- → <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">PNG-Bild-Testdateiliste</a>
Verwandte Artikel
- → <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">So testen Sie das Datei-Upload-Limit korrekt</a>
- → <a href="/ja/blog/mb-vs-mib-file-size/" class="text-primary-600 dark:text-primary-400 hover:underline">MB und MiB sind unterschiedlich! Die Fallstricke von Dateigröße-Einheiten</a>