Установка заголовка Content-Type типа application в PHP

Раздел: Веб-разработка -> HTTP заголовки и контент

Основные методы установки Content-Type application в PHP

Какой самый распространённый способ отдать JSON-данные с правильным заголовком?

Наиболее эффективное решение - использование функции header() перед выводом данных. Для JSON это выглядит так:

header('Content-Type: application/json; charset=utf-8');
echo json_encode($data);

Функция header() модифицирует HTTP-заголовки ответа. Важно вызывать её до любого вывода, иначе PHP выдаст предупреждение и заголовок не установится. Кодировку charset=utf-8 рекомендуется добавлять для корректной обработки Unicode-символов.

Как установить заголовок для отдачи XML через PHP?

Для XML используйте application/xml или text/xml (первый предпочтительнее согласно спецификации). Пример:

$xml = '<root><item>значение</item></root>';
header('Content-Type: application/xml; charset=utf-8');
echo $xml;

Проблема: если XML содержит символы, недопустимые в текущей кодировке, браузер может отобразить кракозябры. Решение: явно указывать charset и следить за кодировкой данных.

Каким образом отправлять бинарные файлы (например, изображения) с заголовком application/octet-stream?

Для принудительной загрузки файла используется application/octet-stream. Пример:

$file = 'image.jpg';
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Length: '.filesize($file));
readfile($file);

Ошибка: если файл большой, может не хватить памяти для readfile(). Решение: использовать буферизованный вывод или fpassthru() с меньшим размером чанка.

Как динамически определить Content-Type на основе расширения файла?

Можно использовать функцию mime_content_type() или finfo для получения MIME-типа. Пример:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
finfo_close($finfo);
header('Content-Type: '.$mime);
readfile($path);

Проблема: на некоторых хостингах расширение fileinfo может быть отключено. Альтернатива - статический массив соответствий расширений.

Какие проблемы возникают при неправильной установке Content-Type?

Например, если для JSON-ответа указать text/html, браузер попытается интерпретировать JSON как HTML, что вызовет ошибку отображения. Или при отдаче CSV с text/plain без указания кодировки может сбиться интерпретация разделителей. Решение: всегда явно задавать корректный MIME-тип и charset.

Расширенные примеры работы с Content-Type application в PHP

1. Отправка JSON с пользовательскими заголовками и CORS

Пример
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
$data = ['status' => 'ok', 'message' => 'Данные получены'];
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
{
    "status": "ok",
    "message": "Данные получены"
}

Пояснение: JSON_UNESCAPED_UNICODE сохраняет кириллицу в читаемом виде, JSON_PRETTY_PRINT форматирует вывод.

2. Отдача PDF-файла с application/pdf

Пример
$file = 'document.pdf';
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="document.pdf"');
header('Content-Length: '.filesize($file));
readfile($file);

Результат: браузер откроет PDF во встроенном просмотрщике. Для принудительной загрузки замените inline на attachment.

3. Передача ZIP-архива на лету

Пример
$zip = new ZipArchive();
$tmpFile = tempnam(sys_get_temp_dir(), 'zip');
if ($zip->open($tmpFile, ZipArchive::CREATE) === TRUE) {
    $zip->addFromString('file.txt', 'Содержимое файла');
    $zip->close();
    header('Content-Type: application/zip');
    header('Content-Disposition: attachment; filename="archive.zip"');
    header('Content-Length: '.filesize($tmpFile));
    readfile($tmpFile);
    unlink($tmpFile);
}
Скачивается архив archive.zip с одним файлом file.txt

4. Использование ob_start для предотвращения вывода до header

Пример
ob_start();
// здесь может быть любой код, который случайно выводит текст
$data = ['key' => 'value'];
header_remove('Content-Type'); // сброс, если заголовок уже установлен
header('Content-Type: application/json');
ob_end_clean(); // очищаем буфер и отправляем заголовки
echo json_encode($data);

Этот подход позволяет избежать ошибки «Cannot modify header information». Однако лучше избегать вывода до header.

5. Динамическое определение MIME-типа через расширение файла (без fileinfo)

Пример
$mimeTypes = [
    'jpg' => 'image/jpeg',
    'png' => 'image/png',
    'gif' => 'image/gif',
    'pdf' => 'application/pdf',
    'zip' => 'application/zip',
];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (isset($mimeTypes[$ext])) {
    header('Content-Type: '.$mimeTypes[$ext]);
    readfile($filename);
} else {
    header('HTTP/1.1 415 Unsupported Media Type');
    echo 'Неподдерживаемый тип файла';
}
При запросе image.jpg браузер получит заголовок Content-Type: image/jpeg

6. Отправка нескольких частей в одном ответе (multipart) – редкость

Пример
$boundary = 'boundary123';
header('Content-Type: multipart/mixed; boundary="'.$boundary.'"');
$body = "--$boundary\r\n";
$body .= "Content-Type: text/plain; charset=utf-8\r\n\r\n";
$body .= "Первая часть\r\n";
$body .= "--$boundary\r\n";
$body .= "Content-Type: application/json\r\n\r\n";
$body .= json_encode(['msg' => 'Вторая часть'])."\r\n";
$body .= "--$boundary--\r\n";
echo $body;
Нестандартный случай, используется редко, например в некоторых API.

Content-Type application в PHP - comments

En
Php content type application (php)