HTTP_RANGEではまる

動画などの大きなファイルを送信するときにファイルの一部をリクエストする「206 Partial Content」があるんだけれども、これではまったのでメモ

HTTP_RANGEで必ずしも終了値がリクエストヘッダに含まれるわけではない

クライアントからのリクエストヘッダでHTTP_RANGEの形式は

Range: bytes=0-1000

みたいになっているんだけど、これが

Range: bytes=0-

のように終了値がしていされないリクエストがあった

んで、レスポンスヘッダ側では「Contents-Length」にてRangeの範囲のサイズを返さないといけないんだけれども、単純に以下のような計算式でやっていると終了値がない場合に「Contents-Length」の値がマイナスになってしまってまずい

<?php
list($dummy, $range) = explode('=', $_SERVER['HTTP_RANGE']);
list($start, $end) = explode('-', $range);

// これだと $end が空で $start が 100 とかだと $contents_length が -99 になってしまう
$contents_length = $end - $start + 1;

header('Content-Length: ' . $contents_length);
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $file_size);

解決方法

まぁ、簡単に終了値がない場合はファイルのサイズを使いましょうってこと

<?php
list($dummy, $range) = explode('=', $_SERVER['HTTP_RANGE']);
list($start, $end) = explode('-', $range);
if(is_null($end)){
	$end = $file_size;
}

$contents_length = $end - $start + 1;

header('Content-Length: ' . $contents_length);
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $file_size);