PHP readfile 无法在 Safari 中正常工作
PHP readfile not working correctly with Safari
我正在将 mp3 加载到 html <audio>
标签中。该标签的来源实际上是一个 php 脚本,其中 returns 一首未托管在 public 目录中的歌曲。
省略大部分验证和其他代码,用于输出 mp3 的 header 是:
header( 'Content-type: {$mime_type}' );
header( 'Content-length: ' . filesize( $file ));
header( 'Content-Disposition: inline;filename="'.$filename.'"' );
header( 'Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0' );
header( 'Pragma: no-cache' );
header( 'Content-Transfer-Encoding: binary');
header( 'Expires: 0');
readfile( $file );
这适用于 Firefox、Chrome(和移动设备)、Edge(和移动设备)和 Opera。但是我似乎无法让 Safari 将生成的 url 用作音频源。实际上,页面呈现后 DOM 中没有出现音频源:
url 可能看起来像 www.website.com/song.php?sid=234234234234
我已经多次尝试调整此文件,但无法弄清楚为什么会在 Safari 上发生这种情况。我的直觉是浏览器处理mp3之类的方式,应该在header中处理。
如有任何指导、提示或帮助,我们将不胜感激。
谢谢。
更新:
添加了网络,显示它加载了 mp3 但第二个请求没有?
响应headers:
Name Value
Server Apache
Content-Type audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3
Date Wed, 28 Dec 2016 17:24:48 GMT
Cache-Control no-cache
X-Powered-By PHP/5.3.29
Content-Disposition inline;filename="148_2793d1c49976a3689147634359577ec1aa5619f1.mp3"
Content-Length 834312
Expires 0
Connection Keep-Alive
Content-Transfer-Encoding binary
Accept-Ranges bytes
Keep-Alive timeout=5, max=100
Pragma no-cache
您需要传递多个范围 header,因为它是部分内容:http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
header("Accept-Ranges: 0-filesize( $file )");
编辑
您需要为 Safari 定义一些 header,即使是移动版本。
我前段时间遇到过这个问题,抱歉,如果我没记错我是如何解决的,但这是一个 header 问题(这是我记得的主要部分,我不使用评论添加答案,因为它太长了)
试试这个..
header( 'Accept-Ranges: bytes');
header("Pragma: public");
header("Expires: 0");
header('Cache-Control: no-cache, no-store');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: inline; filename="'.$filename.'"');
header('Content-Length: '.$fsize);
header('Content-Type: audio/'.$t);
header('Accept-Ranges: bytes');
header('Connection: Keep-Alive');
header('Content-Range: bytes 0-'.$shortlen.'/'.$fsize);
header('X-Pad: avoid browser bug');
header('Etag: '.$etag);
其中:
$filename = "myaudio.mp3";
$path = 'music/'.$filename;
$fsize = filesize($path);
$shortlen = $fsize - 1;
$fp = fopen($path, 'r');
$etag = md5(serialize(fstat($fp)));
fclose($fp);
$t = "mpeg";
希望这对您有所帮助,但是如果我没记错的话,您需要的 2 个主要 header 是 "Etag" 和 "Accept-Ranges"。
我正在将 mp3 加载到 html <audio>
标签中。该标签的来源实际上是一个 php 脚本,其中 returns 一首未托管在 public 目录中的歌曲。
省略大部分验证和其他代码,用于输出 mp3 的 header 是:
header( 'Content-type: {$mime_type}' );
header( 'Content-length: ' . filesize( $file ));
header( 'Content-Disposition: inline;filename="'.$filename.'"' );
header( 'Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0' );
header( 'Pragma: no-cache' );
header( 'Content-Transfer-Encoding: binary');
header( 'Expires: 0');
readfile( $file );
这适用于 Firefox、Chrome(和移动设备)、Edge(和移动设备)和 Opera。但是我似乎无法让 Safari 将生成的 url 用作音频源。实际上,页面呈现后 DOM 中没有出现音频源:
url 可能看起来像 www.website.com/song.php?sid=234234234234
我已经多次尝试调整此文件,但无法弄清楚为什么会在 Safari 上发生这种情况。我的直觉是浏览器处理mp3之类的方式,应该在header中处理。
如有任何指导、提示或帮助,我们将不胜感激。
谢谢。
更新:
添加了网络,显示它加载了 mp3 但第二个请求没有?
响应headers:
Name Value
Server Apache
Content-Type audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3
Date Wed, 28 Dec 2016 17:24:48 GMT
Cache-Control no-cache
X-Powered-By PHP/5.3.29
Content-Disposition inline;filename="148_2793d1c49976a3689147634359577ec1aa5619f1.mp3"
Content-Length 834312
Expires 0
Connection Keep-Alive
Content-Transfer-Encoding binary
Accept-Ranges bytes
Keep-Alive timeout=5, max=100
Pragma no-cache
您需要传递多个范围 header,因为它是部分内容:http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
header("Accept-Ranges: 0-filesize( $file )");
编辑
您需要为 Safari 定义一些 header,即使是移动版本。
我前段时间遇到过这个问题,抱歉,如果我没记错我是如何解决的,但这是一个 header 问题(这是我记得的主要部分,我不使用评论添加答案,因为它太长了)
试试这个..
header( 'Accept-Ranges: bytes');
header("Pragma: public");
header("Expires: 0");
header('Cache-Control: no-cache, no-store');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: inline; filename="'.$filename.'"');
header('Content-Length: '.$fsize);
header('Content-Type: audio/'.$t);
header('Accept-Ranges: bytes');
header('Connection: Keep-Alive');
header('Content-Range: bytes 0-'.$shortlen.'/'.$fsize);
header('X-Pad: avoid browser bug');
header('Etag: '.$etag);
其中:
$filename = "myaudio.mp3";
$path = 'music/'.$filename;
$fsize = filesize($path);
$shortlen = $fsize - 1;
$fp = fopen($path, 'r');
$etag = md5(serialize(fstat($fp)));
fclose($fp);
$t = "mpeg";
希望这对您有所帮助,但是如果我没记错的话,您需要的 2 个主要 header 是 "Etag" 和 "Accept-Ranges"。