しばらく悩んでいて漸く実装できたのでメモ。多分これが最小構成。
<?php
$fp = fopen("./test.3gp2", "r");
while (!feof($fp)) {
$contents_data .= fread($fp,1024);
}
fclose($fp);
if (array_key_exists("HTTP_RANGE", $_SERVER)) {
list($dummy, $start, $end) = preg_split("/[=\-]/", $_SERVER['HTTP_RANGE']);
$total_size = strlen($contents_data);
$contents_data = substr($contents_data, $start, ($end + 1 - $start));
}
header("HTTP/1.1 206 Partial Content");
header("Accept-Ranges: bytes");
header("Content-Range: bytes " . $start . "-" . $end . "/" . $total_size);
header("Content-Type: video/3gpp2");
echo $contents_data;
exit();
?>
分割した分だけこのスクリプトが実行されるので、ダウンロード時に何かの処理をさせたい場合には注意。$startや$endの値で判別すること。あと、通常のリクエストではRangeヘッダを送ってこないのでObject要素でリンクする。ひょっとしたらやれる方法があるかもしれないけど、未調査。