Я играю с моим любимым проектом и, экспериментируя с mp3-потоком с PHP, я всегда получаю звуковую длительность, чтобы вернуть Infinity
. Я пытаюсь искать во многих местах, к сожалению, я не могу найти корневую проблему.
Заметьте, что мне пришлось отложить этот проект на некоторое время, и все прошло хорошо. Когда я возобновил работу над проектом, я сделал некоторый рефактор UI и узнал об этой «ошибке». Может ли кто-нибудь обнаружить что-то не так с моим кодом?
Контекст: это действие контроллера (ZF2), где $media
– модель POPO .
$file = $basePath . $media->getFileName(); $fileSize = filesize($file); $fileHandle = fopen($file, 'r'); $etag = md5(serialize(fstat($fileHandle))); $cacheExpires = new \DateTime(); // TODO : implement ranges... if ( isset($_SERVER['HTTP_RANGE']) ) { // find the requested range // this might be too simplistic, apparently the client can request // multiple ranges, which can become pretty complex, so ignore it for now preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches); $rangeFrom = intval($matches[1]); $rangeTo = intval($matches[2]); $statusCode = 206; } else { $rangeFrom = 0; $rangeTo = $fileSize; $statusCode = 200; } fseek($fileHandle, $rangeFrom); set_time_limit(0); // try to disable time limit $response = new Stream(); $response->setStream($fileHandle); $response->setStatusCode($statusCode); $response->setStreamName(basename($file)); $headers = new Headers(); $headers->addHeaders(array( 'Pragma' => 'public', 'Expires' => $cacheExpires->format('Y/m/d H:i:s'), 'Cache-Control' => 'no-cache', 'Accept-Ranges' => 'bytes', 'Content-Description' => 'File Transfer', 'Content-Transfer-Encoding' => 'binary', 'Content-Disposition' => 'attachment; filename="' . basename($file) .'"', 'Content-Type' => 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3', // $media->getFileType(), 'Content-Range' => "bytes {$rangeFrom}-{$rangeTo}/{$fileSize}", 'Content-Length' => $fileSize, 'Etag' => $etag, 'X-Pad' => 'avoid browser bug', )); $response->setHeaders($headers); return $response;
Я пробовал играть практически со всеми полями HEADER (даже удаляя диапазоны), но браузер всегда получает isFinite(audio.duration) === false
. Все остальное, похоже, работает, включая воспроизведение, безупречно.
Наконец, я нашел свое решение. Мне пришлось слегка изменить код, и вот изменения. Теперь, если я могу полностью поддерживать несколько диапазонов, это будет полным.
(Я делюсь этим, потому что все, что я вижу, это неполные ответы. Надеюсь, это тоже поможет кому-то.)
$file = $basePath . $media->getFileName(); $fileSize = filesize($file); $fileTime = date('r', filemtime($file)); $fileHandle = fopen($file, 'r'); $rangeFrom = 0; $rangeTo = $fileSize - 1; $etag = md5(serialize(fstat($fileHandle))); $cacheExpires = new \DateTime(); if (isset($_SERVER['HTTP_RANGE'])) { if (!preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/i', $_SERVER['HTTP_RANGE'])) { $statusCode = 416; } else { $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6)); foreach ($ranges as $range) { $parts = explode('-', $range); $rangeFrom = intval($parts[0]); // If this is empty, this should be 0. $rangeTo = intval($parts[1]); // If this is empty or greater than than filelength - 1, this should be filelength - 1. if (empty($rangeTo)) $rangeTo = $fileSize - 1; if (($rangeFrom > $rangeTo) || ($rangeTo > $fileSize - 1)) { $statusCode = 416; } else { $statusCode = 206; } } } } else { $statusCode = 200; } if ($statusCode == 416) { $response = $this->getResponse(); $response->setStatusCode(416); // HTTP/1.1 416 Requested Range Not Satisfiable $response->addHeaderLine('Content-Range', "bytes */{$fileSize}"); // Required in 416. } else { fseek($fileHandle, $rangeFrom); set_time_limit(0); // try to disable time limit $response = new Stream(); $response->setStream($fileHandle); $response->setStatusCode($statusCode); $response->setStreamName(basename($file)); $headers = new Headers(); $headers->addHeaders(array( 'Pragma' => 'public', 'Expires' => $cacheExpires->format('Y/m/d H:i:s'), 'Cache-Control' => 'no-cache', 'Accept-Ranges' => 'bytes', 'Content-Description' => 'File Transfer', 'Content-Transfer-Encoding' => 'binary', 'Content-Disposition' => 'attachment; filename="' . basename($file) .'"', 'Content-Type' => 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3', // $media->getFileType(), 'Content-Length' => $fileSize, 'Last-Modified' => $fileTime, 'Etag' => $etag, 'X-Pad' => 'avoid browser bug', )); if ($statusCode == 206) { $headers->addHeaderLine('Content-Range', "bytes {$rangeFrom}-{$rangeTo}/{$fileSize}"); } $response->setHeaders($headers); } return $response;