Функция header в php

Заголовки на скачивание файла коротко описаны здесь — https://blog.bullgare.com/2010/01/%d0%b7%d0%b0%d0%b3%d0%be%d0%bb%d0%be%d0%b2%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%81%d0%ba%d0%b0%d1%87%d0%b8%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5-%d1%84%d0%b0%d0%b9%d0%bb%d0%b0/

Функция header в php используется для посылки HTTP-заголовков (почитать на w3.org).

void header  ( string $string  [, bool $replace = true  [, int $http_response_code  ]] )

$string:
сам заголовок. Бывает двух типов. Первый начинается с «HTTP/» (header(«HTTP/1.0 404 Not Found»);). Второй начинается не с «HTTP/». Состоит из двух частей «имя парметра: значение» (например, «Location: http://www.example.com/» или «Content-type: application/pdf»).
Второй параметр булевого типа. Если true (по умолчанию), то заголовок замещает предыдущий с таким же именем параметра, если false, то передаётся несколько параметров одного типа:

<?php
header('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM', false);
?>

Третий параметр, $http_response_code, можно использовать для передачи HTTP-заголовков ответа (200, 404 и т.п.):

// 301 Moved Permanently
header("Location: /foo.php",TRUE,301);

// 302 Found
header("Location: /foo.php",TRUE,302); //это значение по умолчанию.
header("Location: /foo.php");//аналогично

// 303 See Other
header("Location: /foo.php",TRUE,303);

// 307 Temporary Redirect
header("Location: /foo.php",TRUE,307);

Функция header используется для простановки заголовков «вручную», для кеширования, для внешнего перенаправления, для выставления правильного mime-типа и кодировки.

Пример простановки заголовков «вручную»:

ob_start();
@header("HTTP/1.1 503 Service Temporarily Unavailable");
@header("Status: 503 Service Temporarily Unavailable");
@header("Retry-After: 120");
@header("Connection: Close");
?><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>503 Service Temporarily Unavailable</title>
</head><body>
<h1>Service Temporarily Unavailable</h1>
<p>The server is temporarily unable to service your
request due to maintenance downtime or capacity
problems. Please try again later.</p>
</body></html><?php
echo ob_get_clean();
exit();

Пример внешнего перенаправления:

	public static function redirect($url = '/')
	{
		header('Location: ' . $url);
		die();
	}

Пример реализации скачивания файлов по расширению (полезен перечислением mime-типов):

<?php

function dl_file($file){

    //First, see if the file exists
    if (!is_file($file)) { die("404 File not found!"); }

    //Gather relevent info about file
    $len = filesize($file);
    $filename = basename($file);
    $file_extension = strtolower(substr(strrchr($filename,"."),1));

    //This will set the Content-Type to the appropriate setting for the file
    switch( $file_extension ) {
      case "pdf": $ctype="application/pdf"; break;
      case "exe": $ctype="application/octet-stream"; break;
      case "zip": $ctype="application/zip"; break;
      case "doc": $ctype="application/msword"; break;
      case "xls": $ctype="application/vnd.ms-excel"; break;
      case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
      case "gif": $ctype="image/gif"; break;
      case "png": $ctype="image/png"; break;
      case "jpeg":
      case "jpg": $ctype="image/jpg"; break;
      case "mp3": $ctype="audio/mpeg"; break;
      case "wav": $ctype="audio/x-wav"; break;
      case "mpeg":
      case "mpg":
      case "mpe": $ctype="video/mpeg"; break;
      case "mov": $ctype="video/quicktime"; break;
      case "avi": $ctype="video/x-msvideo"; break;

      //The following are for extensions that shouldn't be downloaded (sensitive stuff, like php files)
      case "php":
      case "htm":
      case "html":
      case "txt": die("Cannot be used for ". $file_extension ." files!>"); break;

      default: $ctype="application/force-download";
    }

    //Begin writing headers
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
   
    //Use the switch-generated Content-Type
    header("Content-Type: $ctype");

    //Force the download
    $header="Content-Disposition: attachment; filename=".$filename.";";
    header($header );
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".$len);
    @readfile($file);
    exit;
}
?>

*Mime-типы описываются здесь.

Заголовок header(«Content-Transfer-Encoding: binary»); очень важен для того, чтобы заставить браузер скачивать файл, а не отображать текстовое содержимое.

Пример установки использумой кодировки:

	header('Content-type: text/html; charset=utf-8');
	header('Content-type: text/xml; charset=utf-8');

Самая интересная часть: кеширование (w3.org).
Для начала надо заметить, что HTTP/1.0 моежт не поддерживать основную директиву (Cache-Control), поэтому в этом случае нужно использовать заголовок Pragma: no-cache. Хотя уже давно все поддерживают 1.1, поэтому особого смысла это делать нет.
Заголовок Cache-Control может использоваться как для запроса, так и для ответа. Нас интересует только ответ.
Синтаксис следующий:
«Cache-Control: значение».
Значения:

"public" //может кешироваться всеми (прокси-серверами тоже)                              
"private" //может кешироваться клиентом
"no-cache" //должен кешироваться клиентом (есть ещё доп. параметры)
"no-store" //не сохранять на диске
"no-transform" //для прокси-серверов запрещает изменять тип файла (для картинок, к примеру)
"must-revalidate" //все должны подтвердить наличие кеша
"proxy-revalidate" //прокси должен подтвердить наличие кеша
"max-age" "=" delta-seconds //закешировать на это время
"s-maxage" "=" delta-seconds //для общего кеша (не private) переопределяет значение "max-age" и заголовок "Expires:"
Например:
Cache-Control: max-age=значение

Заголовок Expires используется для задания даты, при которой кеш считается просроченным
(Expires: Thu, 01 Dec 1994 16:00:00 GMT), можно задавать дату в прошлом (значит, кеш уже просрочен) или в будущем. При этом если используется заголовок Cache-Control: max-age=значение, то он переопределяет заголовок Expires.
Заголовок ETag используется для создания «тегов», по сравнению которых можно определить, актуален ли кеш в браузере/на прокси-сервере.
Использование:
ETag: уникальный тег.
Обычно для создания тегов советуют использовать что-то вроде:

$etag = md5_file($file);
header("Etag: $etag");

Думаю, для кеширования картинок вполне достаточно этого:

$etag = filesize($file);
header("Etag: $etag");

Но только делать такие вещи в том же Nginx (возможно там такой механизм уже есть).
Для запрета кеширования обычно используется связка

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past

UPD:

А вообще, если интересно, вот очень большой список майм-типов:
https://github.com/broofa/node-mime/blob/master/types/mime.types

https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1

5 комментариев so far.

  1. марлен:
    спасибо! что детально и подробно!!!
  2. ator:
    А можно добавить SWF файлы в скрипт?
    • bullgare:
      для flash нужен заголовок
      header(«Content-Type: application/x-shockwave-flash»);
      т.е.
      в скрипте после строки
      case «avi»: $ctype=»video/x-msvideo»; break;
      нужно добавить
      case «swf»: $ctype=»application/x-shockwave-flash»; break;
  3. а как добавить rar-архивы???
  4. bullgare:
    case ‘rar’: $ctype = ‘application/x-rar-compressed, application/octet-stream’; break;
    case ‘zip’: $ctype = ‘application/zip, application/octet-stream’; break;

LEAVE A COMMENT