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 )");

编辑

看看这里: http://www.techstruggles.com/mp3-streaming-for-apple-iphone-with-php-readfile-file_get_contents-fail/

您需要为 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"。