问题 PHP流媒体MP3


我问的人情况非常相似: 我可以用PHP提供MP3文件吗? 基本上我试图保护mp3文件免受直接下载,因此用户必须先通过php才能获得首次验证。 这是我的代码:

header('Content-type: audio/mpeg');
header('Content-length: ' . filesize($file));
header('X-Pad: avoid browser bug');
Header('Cache-Control: no-cache');
header("Content-Transfer-Encoding: binary"); 
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
readfile($file);

这是我的问题:文件只播放一小部分(通过浏览器中的Quicktime)然后停止 - Quicktime似乎认为 文件的长度只与它设法下载的块一样长。当我重新加载时 - 它会播放一个稍微大一点的块 - 无论它设法下载到那一点。

这是我发送的标题中的问题吗?我该如何传输这样的文件? 如果swf正在从该文件中读取,这是一个问题吗?

谢谢!


谢谢你们所有答案。虽然这些事情都没有解决问题,但其中许多人都把我引向了正确的方向。非常感激。 有关完整解决方案,请参阅下面的答案


2911
2018-03-01 18:53


起源

我认为你的真实代码中没有那个拼写错误(“标题”)?此外,您不需要X-Pad黑客。这只是古代网景的必要条件(见 george.hotelling.net/90percent/geekery/...)。您不需要Content-Transfer-Encoding,您应该只指定Content-Type一次(audio / mpeg很好)。 - Matthew Flaschen
@Matthew Flaschen:PHP函数不区分大小写,因此它只是一个一致性问题。 Content-Type可能是真正的问题。 - Piskvor


答案:


这就是诀窍。

$dir = dirname($_SERVER['DOCUMENT_ROOT'])."/protected_content";
$filename = $_GET['file'];
$file = $dir."/".$filename;

$extension = "mp3";
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3";

if(file_exists($file)){
    header('Content-type: {$mime_type}');
    header('Content-length: ' . filesize($file));
    header('Content-Disposition: filename="' . $filename);
    header('X-Pad: avoid browser bug');
    header('Cache-Control: no-cache');
    readfile($file);
}else{
    header("HTTP/1.0 404 Not Found");
}

7
2018-03-02 22:54



您可能希望在阅读之前对$ _GET ['file']进行一些验证/清理...... - Simon
我检查文件是否存在 if(file_exists($file)){... 这是你的意思吗? - Yuval Karmi
不,他不是那个意思。想一想,如果有人试图这样做会发生什么 yoursite.com/yourscript.php?file=../../../home/... - Jonny
是的,你非常需要有效的用户请求 - Ata
它很棒,但不可寻找!! - Moh Arjmandi


如果您的服务器在apache或lighty上运行,我建议您查看x-sendfile

http://tn123.ath.cx/mod_xsendfile/

这允许您在php应用程序中处理身份验证,但让您的Web服务器处理文件的传输。你获得的性能提升应该是一个很好的额外好处


1
2018-03-01 18:57





你可以试试 HTTP分块。将“Transfer-Encoding”标头设置为“chunked”,然后在发送之前输出每个块的大小。使用CRLF结束每个块大小和块。

对于任何更复杂的事情,我建议使用流媒体服务器,例如 的Icecast


1
2018-03-01 18:58





有两点突出:

  1. 你有一个 Content-Length 组。如果您将服务器设置为自动gzip您的输出,这可能会搞乱。试着关掉 Content-Length 并看看是否修复它。
  2. 你有大约一千个 Content-Type设定。因为你服用的是Mp3,所以只需使用即可 audio/mpeg。你可以有效地摆脱整个过去 header() 命令。使用HTTP标头很容易被搞砸。

尝试一下,让我们知道它是怎么回事!


1
2018-03-01 21:27





去掉 header("Content-Transfer-Encoding: binary"); 而且你会被设定!


0
2018-03-09 00:53





对于这些解决方案,您还需要在apache(mod_xsendfile)或nginx HttpSecureLinkModule中配置xsendfile - 它们将为您提供精确的mp3,因此浏览器将正确播放


0
2018-06-06 12:18





不幸的是,应用所有这些有效隐藏原始路径和文件名的解决方案并不能防止未经授权的下载。 确实客户端(在我的情况下:Chrome)下载文件。

这里我放在我的服务器上的行:

<?php
$dir = dirname($_SERVER['DOCUMENT_ROOT'])."/mp3";
$filename = $_GET['file'];
$file = $dir."/".$filename;

$extension = "mp3";
$mime_type = "audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3";

if(file_exists($file)){
    header('Content-type: {$mime_type}');
    header('Content-length: ' . filesize($file));
    header("Content-Transfer-Encoding: binary"); 
    header('Content-Disposition: filename="' . $filename);
    header('X-Pad: avoid browser bug');
    header('Cache-Control: no-cache');
    readfile($file);
}else{
    header("HTTP/1.0 404 Not Found");
}
?>

有或没有线

    header("Content-Transfer-Encoding: binary"); 

最终结果不会改变 目录/ mp3位于

/home/myuser/

(因此/ home / myuser / mp3) 和公共HTML目录是

/home/myuser/public_html

因此调用我的域名并给予

/player.php?file=music.mp3

它会下载一个名为music.mp3的文件,其中包含所有原始内容。


0
2018-03-31 14:05