PHP 流媒体 MP3

发布于 2024-08-23 04:57:45 字数 793 浏览 11 评论 0原文

我和提问者的情况很相似: 我可以使用 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 正在从该文件读取,是否有问题?

谢谢!


谢谢大家的回答。尽管这些事情都不能完全解决问题,但其中许多都给我指明了正确的方向。非常感谢。 对于完整的解决方案,请参阅下面我的回答

I have a very similar situation to the person who asked:
Can I serve MP3 files with PHP?
Basically I am trying to protect mp3 files from direct download, so users have to go through php to get authenticated first.
Here's my code:

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

Here's my problem: The file only plays a very small chunk of the beginning (via Quicktime in the browser) and then stops - Quicktime seems to think the length of the file is only as long as the chunk it managed to download. When I reload - it plays a slightly larger chunk - whatever it managed to download up to that point.

Is that a problem in the headers I am sending? How would I stream such a file?
Is it a problem if an swf is reading from that file?

Thanks!


Thank you guys for all the answers. Although none of these things were exactly what solved the problem, many of them sent me in the right direction. Much appreciated.
For the full solution see my answer below

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

憧憬巴黎街头的黎明 2024-08-30 04:57:45

这就是成功的秘诀。

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

Here's what did the trick.

$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");
}
情感失落者 2024-08-30 04:57:45

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

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

You can try HTTP chunking. Set the "Transfer-Encoding" header to "chunked", then output the size of each chunk before sending it. End each chunk size and chunk with a CRLF.

For anything more complex, I recommend using a streaming server, such as Icecast.

梦纸 2024-08-30 04:57:45

有两件事很突出:

  1. 您已经设置了 Content-Length 。如果您的服务器设置为自动对输出进行 gzip 压缩,这可能会造成混乱。尝试关闭 Content-Length 并查看是否可以解决问题。
  2. 您已经设置了大约一千个 Content-Type。由于您提供的是 Mp3,因此只需使用 audio/mpeg。您可以有效地摆脱最后一个 header() 命令。人们很容易被 HTTP 标头迷惑。

尝试一下,让我们知道效果如何!

Two things stand out:

  1. You've got a Content-Length set. If you server is set to automatically gzip your output, this can mess with things. Try turning off Content-Length and see if that fixes it.
  2. You've got about a thousand Content-Types set. Since it's Mp3 that you're serving, just use audio/mpeg. You can effectively get rid of the whole last header() command. It's easy to get carried away with HTTP headers.

Try it out and let us know how it goes!

童话 2024-08-30 04:57:45

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

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

这允许您在 php 应用程序中处理身份验证,但让您的网络服务器处理文件的传输。您获得的性能改进应该是一个不错的额外好处

if your server is running on apache or lighty, i would suggest you look into x-sendfile

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

this allows you to handle authentication in your php application, but let's your webserver handle the transmission of the file. the performance improvement you gain should be a nice additional benefit

勿忘初心 2024-08-30 04:57:45

删除 header("Content-Transfer-Encoding: binary"); 然后你就准备好了!

Remove header("Content-Transfer-Encoding: binary"); And you'll be set!

別甾虛僞 2024-08-30 04:57:45

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

For these solution you also need to configure xsendfile in apache (mod_xsendfile) or nginx HttpSecureLinkModule - they will give you exact mp3, so browser will play it correctly

人心善变 2024-08-30 04:57:45

不幸的是,应用所有这些可有效隐藏原始路径和文件名的解决方案并不能防止未经授权的下载。
事实上,客户端(在我的例子中: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 的文件,其中包含所有原始内容。

Applying all these solutions, which are valid to hide the original path and filename, unfortunately doesn't prevent from unauthorized download.
Indeed the client (on my case: Chrome) downloads the file.

Here the lines I put on my server:

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

with or without the line

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

the final result doesn't change
The directory /mp3 is located into

/home/myuser/

(thus /home/myuser/mp3)
and the public HTML directory is

/home/myuser/public_html

thus calling my domain and giving

/player.php?file=music.mp3

it downloads a file called music.mp3 with all the original content.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文