最近,在项目中尝试使用html5中的audio标签做web版的播放器,因为涉及到付费的音频,所以需要对用户权限做一些判断,然后动态输出mp3。但是,动态生成的mp3在chrome中无法正常拖动。
我们来看一下代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<audio src="http://localhost/demo/mp3.php" controls="controls"></audio>
</body>
</html>
header("Content-type:audio/mpeg");
header('Content-Length: ' . filesize("1.mp3"));
echo file_get_contents("1.mp3");
进度条不能拖动
将audio中的src修改成mp3源文件路径:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<audio src="http://localhost/demo/1.mp3" controls="controls"></audio>
</body>
</html>
在chrome中拖动正常
猜想,莫非audio播放mp3后缀的音频文件才能拖动进度条?
尝试配置apache解析后缀为mp3的php文件,将mp3.php改成mp3.mp3,问题依然存在。
取消掉apache解析后缀为mp3文件的行为,将audio标签中的src修改为mp3源文件路径,利用chrome控制台查看audio标签如何请求以及响应。
1.mp3的请求信息:
请求头里面主要包含Range字段。 响应信息如下:
响应的状态码:
响应头信息:
主要包含Accept-Ranges、Content-Range字段。 很明显,chrome请求mp3文件时采用的是断点续传。 当点击进度条时,相应的请求信息及响应信息如下:
当点击进度条时,chrome浏览器会发起一条http请求,依然采用断点续传。
根据以上分析,若要使动态生成的mp3能拖动进度,就必须在php文件中实现断点续传,在php中构造相应的响应头即可。
最终,mp3.php代码如下:
<?php
$file = "1.mp3";
$fileSize = filesize($file);
$etag = md5(filemtime($file));
$fp = fopen($file, 'rb');
if (!$fp) {
die('Could not open file');
}
$start = 0;
$end = $fileSize - 1;
if (isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])) {
//获取请求头中的Range字段
$range = explode('-', substr($_SERVER['HTTP_RANGE'], strlen('bytes=')));
$start = $range[0];
if ($range[1] > 0) {
$end = $range[1];
}
//构造断点续传响应头
header('HTTP/1.1 206 Partial Content');
header('Status: 206');
header('Accept-Ranges: bytes');
header('Content-Range: bytes ' . $start. '-' . $end . '/' . $fileSize);
header('Content-Length: ' . ($end - $start + 1));
} else {
header('Content-Length: ' . $fileSize);
}
header('Content-Type: audio/mpeg');
header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T', filemtime($file)));
header('ETag: "' . $etag . '"');
header('Expires: 0');
if ($start > 0) {
fseek($fp, $start); //移动文件指针
}
$bytesPosition = $start;
while (!feof($fp) && $bytesPosition <= $end) {
$chunk = 1024 * 1024 * 50; //每次读取50k
if ($bytesPosition + $chunk > $end + 1) {
$chunk = $end - $bytesPosition + 1;
}
$chunk = fread($fp, $chunk);
if (!$chunk) {
die('Could not read file');
}
print($chunk);
flush();
$bytesPosition += $chunk;
}
fclose($fp);
至此,在audio标签中便可以使用php动态生成的mp3。