【问题标题】:PHP readfile not working correctly with SafariPHP readfile 无法与 Safari 一起正常工作
【发布时间】:2016-12-29 01:40:40
【问题描述】:

我正在将 mp3 加载到 html <audio> 标记中。该标签的来源实际上是一个 php 脚本,它返回一首不在公共目录中的歌曲。

省略大部分验证和其他代码,用于输出 mp3 的标头是:

    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 中不会出现任何音频源:

网址可能类似于www.website.com/song.php?sid=234234234234

我已尝试多次调整此文件,但无法弄清楚为什么会在 Safari 上发生这种情况。我的直觉是浏览器对mp3之类的处理方式,应该在header中处理。

任何指导、提示或帮助将不胜感激。

谢谢。

更新: 添加了网络,显示它加载了 mp3 但第二个请求没有?

响应标题:

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

【问题讨论】:

  • 如果您在音频标签中看不到src 属性,则问题出在 HTML,而不是 PHP 脚本。它从一开始就不会调用 PHP 脚本。
  • 检查标题响应...因为“header('Content-type: {$mime_type}');”没有替换值,因为即使使用“{}”我也没有错,单引号在 php 中不能用于替换 vars 中的值。尝试将其更改为 header('Content-type: '.$mime_type}');如果不起作用,那么请将网络标头添加到您的问题中(如果我有什么问题,请纠正我:))
  • @Asfo 很好的建议,但没有奏效。以下是网络标头:i.imgur.com/9xsiyqx.png

标签: php audio safari http-headers readfile


【解决方案1】:

您需要传递多个范围标头,因为它是部分内容: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 定义一些标头,即使是移动版也是如此。

【讨论】:

  • 对我不起作用 :( 我已经更新了帖子以包含网络屏幕截图。但如果你有兴趣在本地调试它(safari vs chrome),这里有一个例子leerecs.com/library/index.php?action=recent
  • 我认为你对接受范围是正确的,但我还不能让它工作。嗯。你觉得我的标题有什么过分的地方吗?
  • 我看不到响应标头。无论如何,为什么在请求标头上 Range 标头具有“0-1”?文件大小为 1 字节?
  • 您发布的链接为此提供了一个庞大的库。它现在有效,我非常感谢你——我不认为我会弄明白。干杯。
  • 仅使用 header("Accept-Ranges: 0-filesize( $file )"); 对我不起作用(在 iOS Safari 中),但该链接对我有很大帮助。谢谢!
【解决方案2】:

我前段时间遇到过这个问题,抱歉,如果我不记得我是如何解决这个问题的,但这是一个标题问题(这是我记得的主要部分,我不使用 cmets 来添加答案,因为它太长了)

试试这个..

  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 个主要标题是“Etag”和“Accept-Ranges”。

【讨论】:

    猜你喜欢
    • 2012-01-31
    • 2013-10-10
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 2020-08-19
    相关资源
    最近更新 更多