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
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
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.
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");
}
Remove header("Content-Transfer-Encoding: binary");
And you'll be set!
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.
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