0

我正在尝试使用 HTML5 音频标签通过浏览器提供音频文件:

<audio preload="auto">
    <source src="<?php echo $song->getUrl('mp3'); ?>" type="audio/mpeg">
    <source src="<?php echo $song->getUrl('ogg'); ?>" type="audio/ogg">
    Please update your browser.
</audio>

我需要节省流量,所以我想用这种方式发送部分内容:

$contentType = ($format == 'mp3') ? 'audio/mpeg' : 'audio/ogg';
$filePath = $song->getPath($format);
$fileLength = filesize($filePath);

$start = 0;
if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
    $http_range = explode('-', substr($_SERVER['HTTP_RANGE'], strlen('bytes=')));
    $start = $http_range[0];
}

$remainingBytes = $fileLength - $start;

$length = min((512*1024), $remainingBytes);
$final = $start + $length;

header('HTTP/1.1 206 Partial Content');
header('Status: 206 Partial Content');
header('Content-Type: ' . $contentType);
header('Content-Disposition: inline;filename="listen.' . $format . '"');
header('Content-length: ' . $length);
header('Content-Transfer-Encoding: bytes');
header('Accept-Ranges: bytes');
header('Cache-Control: no-cache');
header('Content-Range: bytes ' . $start . '-' . $final . '/' . $fileLength);
echo file_get_contents($filePath, false, null, $start, $length);

这样做的结果是,在 Chrome 中,歌曲几乎完全播放(9.1MB 文件的 3.47 秒中有 3.41 秒)。在 Firefox 中,播放前 39 秒(我猜是 512KB)。在歌剧中,一个永无止境的“加载”状态。

4

2 回答 2

1

根据 RFC2616206 Partial Content响应仅在响应 HTTP 范围请求时有效:

10.2.7 206 部分内容

服务器已完成对资源的部分 GET 请求。请求必须包含一个 Range 头字段(第 14.35 节)指示所需的范围,并且可以包含一个 If-Range 头字段(第 14.27 节)以使请求有条件。

您的脚本正在为一个请求生成 206 响应,该请求很可能不是针对部分内容(或者可能与您返回的范围不同),这会使 Web 浏览器感到困惑。在大多数浏览器中,很可能没有逻辑可以发出额外的请求来获取您的其余内容,因为这种情况永远不会发生。

您的脚本也没有正确处理 Range 请求!范围包括一个长度,一个请求中可能存在多个范围。同样,请参阅 RFC2616 了解详细信息

于 2013-05-13T15:35:37.373 回答
0

我认为您错误地计算了文件的大小

$contentType = ($format == 'mp3') ? 'audio/mpeg' : 'audio/ogg';
$filePath = $song->getPath($format);
$fileLength = filesize($filePath);

已编辑

$format是文件扩展名而不是文件路径和

filesize($filePath); // Do not returns file size
于 2013-05-13T14:41:22.507 回答