Content-Typeとは

Content-Typeは、HTTPリクエストまたはレスポンスのボディがどの形式かを示す表現ヘッダーです。送信側は、形式が分かっているボディに適切なメディアタイプを付けます。省略時の扱いは受信側によって異なるため、推測に頼らないことが重要です。
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Alice", "email": "alice@example.com"}
役割: リクエストではクライアントからサーバーへ、レスポンスではサーバーからクライアントへ、ボディの解釈方法を伝えます。
MIMEタイプの構造
MIMEタイプは「タイプ/サブタイプ」の形式で表現されます:
type/subtype[; parameter=value]
例:
application/json
text/html; charset=utf-8
multipart/form-data; boundary=----WebKitFormBoundary
| 要素 | 説明 | 例 |
|---|---|---|
| タイプ | データの大分類 | text, application, image |
| サブタイプ | 具体的な形式 | html, json, png |
| パラメータ | 追加情報(オプション) | charset=utf-8 |
ポイント: MIMEタイプは元々メール用の規格(MIME: Multipurpose Internet Mail Extensions)でしたが、HTTPでも採用されました。
よく使うMIMEタイプ一覧
テキスト系
| MIMEタイプ | 説明 | 使用場面 |
|---|---|---|
text/html | HTML文書 | Webページ |
text/plain | プレーンテキスト | ログファイル、テキストファイル |
text/css | CSS | スタイルシート |
text/javascript | JavaScript | スクリプトファイル |
text/csv | CSV | データエクスポート |
# HTML
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<!DOCTYPE html><html>...
アプリケーション系
| MIMEタイプ | 説明 | 使用場面 |
|---|---|---|
application/json | JSON | API通信(最重要) |
application/xml | XML | 古いAPI、設定ファイル |
application/pdf | 文書ダウンロード | |
application/zip | ZIP圧縮ファイル | ファイル配布 |
application/x-www-form-urlencoded | URLエンコードフォーム | HTMLフォーム送信 |
application/octet-stream | バイナリデータ(汎用) | ダウンロード |
# JSON API
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Bob"}
画像・ファイル系
代表例はimage/png、image/jpeg、image/svg+xml、application/pdfです。網羅的な一覧が必要な場合は、IANAのMedia Types Registryを確認します。
# 画像レスポンス
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 12345
(バイナリデータ)
charsetパラメータ
テキスト系のMIMEタイプでは、文字エンコーディングを指定できます:
Content-Type: text/html; charset=utf-8
JSONでは通常Content-Type: application/jsonを使います。JSONの登録情報にはcharsetパラメータが定義されておらず、ネットワーク上のJSONはUTF-8を用いるのが基本です。
主な文字エンコーディング:
| charset | 説明 |
|---|---|
utf-8 | Unicode(推奨、最も一般的) |
iso-8859-1 | Latin-1(欧米言語) |
shift_jis | Shift JIS(日本語、レガシー) |
ポイント: 現代のWebではcharset=utf-8が標準です。特別な理由がない限りUTF-8を使いましょう。
application/x-www-form-urlencoded
HTMLフォームのデフォルトエンコーディング方式:
POST /api/login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
username=alice&password=YOUR_PASSWORD
特徴:
- キー=値のペアを
&で連結 - スペースは
+または%20に変換 - 特殊文字はURLエンコード(
%エンコード)
制約:
- ファイルアップロードには使えない
- バイナリデータには不向き
<!-- HTMLフォーム例 -->
<form method="POST" action="/api/login">
<input name="username" value="alice">
<input name="password" type="password">
<button type="submit">Login</button>
</form>
multipart/form-data
ファイルアップロード用のエンコーディング方式:
POST /api/upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="title"
My Document
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf
(バイナリデータ)
------WebKitFormBoundary7MA4YWxkTrZu0gW--
構造の説明
| 要素 | 説明 |
|---|---|
| boundary | パート境界の識別子(ランダム文字列) |
| Content-Disposition | フィールド名とファイル名 |
| Content-Type | 各パートのMIMEタイプ |
注意: boundaryは各パートの区切りを示す重要な値です。データ内に出現しないランダムな文字列を使う必要があります。
HTMLでのファイルアップロード
<form method="POST" action="/api/upload" enctype="multipart/form-data">
<input type="text" name="title" placeholder="タイトル">
<input type="file" name="file">
<button type="submit">アップロード</button>
</form>
JavaScriptでのファイルアップロード
const formData = new FormData();
formData.append('title', 'My Document');
formData.append('file', fileInput.files[0]);
fetch('/api/upload', {
method: 'POST',
body: formData
// Content-Typeは自動設定される(boundary含む)
});
実践メモ: FormDataを使う場合、Content-Typeを手動設定してはいけません。ブラウザが自動的にboundaryを含めて設定します。
Content-Typeの使い分け
APIリクエスト
| データ形式 | Content-Type | 使用場面 |
|---|---|---|
| JSON | application/json | 現代のREST API |
| URLエンコード | application/x-www-form-urlencoded | シンプルなフォーム |
| ファイルあり | multipart/form-data | ファイルアップロード |
APIレスポンス
# JSON
HTTP/1.1 200 OK
Content-Type: application/json
{"status": "success"}
# HTML
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
<!DOCTYPE html>...
# ファイルダウンロード
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
よくある間違い
1. Content-Typeの指定忘れ
# ❌ 悪い例
POST /api/users HTTP/1.1
{"name": "Alice"}
サーバーがJSONとして解釈できない可能性があります。
# ✅ 良い例
POST /api/users HTTP/1.1
Content-Type: application/json
{"name": "Alice"}
2. charsetの不一致
# ❌ 悪い例(UTF-8で送っているのにShift_JISと宣言)
Content-Type: text/html; charset=shift_jis
(実際はUTF-8のHTML)
文字化けの原因になります。
3. FormDataにContent-Typeを手動設定
// ❌ 悪い例
const formData = new FormData();
formData.append('file', file);
fetch('/api/upload', {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data' // boundaryが欠落
},
body: formData
});
// ✅ 良い例
fetch('/api/upload', {
method: 'POST',
body: formData // Content-Typeは自動設定
});
4. 実データと異なるタイプを返す
画像をtext/htmlとして返すなど、宣言と実データが一致しないと表示失敗や意図しない解釈につながります。特にスクリプトやスタイルを配信するサイトでは、正しいContent-Typeに加えて次のヘッダーでMIME sniffingを無効にする方法があります。
X-Content-Type-Options: nosniff
Content-Typeの判定
サーバー側(Node.js / Express)
app.post('/api/data', (req, res) => {
if (req.is('application/json')) {
// JSONとして処理
console.log(req.body);
} else if (req.is('multipart/form-data')) {
// ファイルアップロードとして処理
console.log(req.files);
} else {
res.status(415).send('Unsupported Media Type');
}
});
クライアント側(JavaScript)
fetch('/api/data')
.then(response => {
const contentType = response.headers.get('Content-Type');
if (contentType?.startsWith('application/json')) {
return response.json();
} else if (contentType?.startsWith('text/html')) {
return response.text();
} else if (contentType?.startsWith('image/')) {
return response.blob();
}
});
まとめ
Content-Typeは、リクエストとレスポンスのボディをどう解釈するか伝えるヘッダーです。JSONはapplication/json、HTMLはtext/html; charset=utf-8、ファイルを含むフォームはmultipart/form-dataを基本にし、宣言と実データを一致させます。
関連記事
- HTTPの基本 - リクエストとレスポンスの構造
- HTTPヘッダー入門 - リクエスト/レスポンスヘッダーの全体像
- HTTPメソッド - GET / POST / PUT / DELETE / PATCH の使い分け
参考リソース
- MDN - Content-Type
- IANA - Media Types Registry
- RFC 9110 - HTTP Semantics (Content-Type)
- RFC 8259 - The JavaScript Object Notation (JSON) Data Interchange Format
- MDN - MIME types (complete list)