PHP (Laravel) обрабатывает запрос, содержащий заголовок Range, возвращает часть контента на клиент.
Примеры заголовков:
// Устанавливаем заголовки ответа
$headers = [
'Content-Type' => 'application/octet-stream',
'Content-Length' => ($end - $start + 1),
'Accept-Ranges' => 'bytes',
'Content-Range' => "bytes $start-$end/$fileSize",
];
Далее ларка формирует streamedResponse и выбрасывает его на клиент через echo:
return new StreamedResponse(function () use ($file, $start, $end) {
// Открываем файл
$handle = fopen($file->getPathname(), 'rb');
// Указатель на нужное место файла
fseek($handle, $start);
$chunkSize = 1_024 * 1_024; // 1MB
$bytesRemaining = $end - $start + 1;
while ($bytesRemaining > 0 && ! feof($handle)) {
$bytesToRead = min($chunkSize, $bytesRemaining);
$buffer = fread($handle, $bytesToRead);
echo $buffer;
flush();
$bytesRemaining -= $bytesToRead;
}
fclose($handle);
}, Response::HTTP_PARTIAL_CONTENT, $headers);
Возник резонный вопрос, на клиенте требуется в плеере отображать общий размер файла (проще говоря, дорожку для файла длиной в 1 минуту равной 1 минуте, при учёте, что каждый раз запрашивается по 10 секунд). В Content-length эту информацию не положишь, так как тогда будет LENGTH_MISMATCH. Гугл предлагает всевозможные варианты решения: засунуть эту мета-инфу напрямую в echo и на клиенте обрезать, анализировать мета-дату файла уже на клиенте (тут ещё вопрос с позицией первого запроса возникает). В данный момент интересует только mp4-формат, поскольку в нём вроде как мета-данные лежат в самом начале, выглядит как самый простой вариант. Как вообще эту задачу решают? Неужели отдельные запросы на мета-данные и сам файл?