使用PHP将stdout上的MP3流式传输到Jplayer

时间:2012-01-06 04:16:20

标签: php header streaming stdout jplayer

我正在使用以下参数初始化jplayer:

$jplayer.jPlayer('setMedia',{
  mp3: data.audioMP3,
  oga: data.audioOGA
});

假设data.autdioMP3(和它的OGA对应物)是php脚本的路径,例如:'http://myserver.local/playaudio.php?songID=99&format=mp3'

我在努力的地方是playaudio.php。我想阅读MP3文件并将其流式传输到jplayer而不会泄露音频路径(这就是为什么我没有使用音频文件路径初始化jplayer)。

类似的东西(部分来自php文档中的the example for readfile):

<?php

$if ($validUser && file_exists($file){
     header('Content-Transfer-Encoding: binary');
     header('Content-Type: audio/mpeg');
     header('Expires: 0');
     header('Cache-Control: must-revalidate');
     header('Content-Length: ' . filesize($file));
     ob_clean();
     flush();
     readfile($file);
     exit;
}
?>

我认为这只会强制下载文件,但是这仍然会向用户显示文件的路径吗?是否有更好的选择将原始mp3数据流式传输给用户,而不会泄露您知道的文件路径?

谢谢!

3 个答案:

答案 0 :(得分:2)

由于您使用javascript来获取文件,其他人可以通过阅读浏览器的标题/文件请求(firebug,Chrome的默认工具等)来执行相同的操作。

保护文件免遭下载的最佳方法是进行一系列检查以获取数据。它并不完美,但除了最坚定的决定之外,它将阻止所有人。对于某些想法,请查看Grooveshark's API上的此页面(这有点旧,缺少一些信息,因此它是完美的参考),或者只是访问Grooveshark / Youtube,看看它们如何保护其内容。

通过巧妙地使用会话和良好的数据库,可以重新创建这种安全性。

答案 1 :(得分:2)

我认为您很难阻止用户发现您的媒体内容网址,我认为这几乎是不可能的(快速查看Chrome上的“网络”标签会显示您加载的曲目,无论您如何编码{ {1}})。

我会说你最好坚持发布你不介意与世界分享的媒体..或者只是发布

  • n 第二次预览
  • 质量较差的版本,例如90bps /单声道

如果您真的想保护自己的资源,可以在服务器端使用oAuth或Access Control。

答案 2 :(得分:1)

感谢大家的回答。

我实际上最终解决了问题而没有向用户透露音频文件的路径。

因为这是针对在线语音消息应用程序,所以保护消息的路径以保护用户的隐私非常重要。

由于消息存储在远程服务器上,这种情况最终变得更加复杂......在我发布此问题后立即发现了这一点。

所以整个过程都是:

1)从远程服务器卷曲MP3文件

2)设置一些标题以强制下载数据,然后将其回显到stdout

由于数据正在标准输出并且标头设置为强制下载,因此jPlayer的效果与在/some/dir/message.mp3中请求文件的效果相同,但请求除外转到/some/dir/playmessage.php - 因此路径永远不会透露给用户。

编辑** - 假设我有访问控制,验证在下面的snippit之前运行,否则暴露下面脚本的路径与暴露mp3的路径没什么不同。 (见我和劳埃德之间的评论)

以下是最终完成工作的代码:

$ch = curl_init($remoteFile);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
$data = curl_exec($ch);
curl_close($ch);
if ($data === false) {
  echo 'CURL Failed';
  exit;
}

//Get file size
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
  $contentLength = (int)$matches[1];
}

//force user to download file contents
header('Content-Transfer-Encoding: binary');
header('Content-Type: audio/mpeg');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Content-Length: ' . $contentLength);
ob_clean();
flush();
echo $data;
exit;
?>

假设$remoteFile是我要在我们存储消息的服务器上播放的mp3文件的路径。

我在reading a remote file using PHP上发现此资源特别有帮助。以下是有关modifying http headers的更多信息。

注意我本质上是两次下载文件,这会减慢用户的进程。可能有更好的方法来做到这一点。 :)如果你在本地保存文件,我最初在我的问题中实际工作(使用readfile()输出原始mp3数据)。