This is partly a PHP question and partly a HTML/client-side question. I'm looking both for technical suggestions and also opinions about what the ideal behavior should be.
I need to make some music files available to listeners. I'm using CodeIgniter but not especially interested in any kind of elaborate plugin with all kinds of bells and whistles that I don't need or awkward file management constraints. I like to keep my MP3 files in a directory outside my web root and grant access via some PHP script which serves as a download proxy so that I can screen bots, ban people, or require login, etc. before granting the file. My primary concern is what should happen when a user clicks on a download link, for instance. Simply linking an MP3 file, in my experience, seems very problematic. Some browsers will try to play the file. Other users will be prompted for a download. Some machines want to launch iTunes.
Can anyone suggest the most elegant way to make audio files available? The best possible solution would work both on browsers and on phones. If there's some way to import the song into one's phone music library, that would be THA BOMB. Although I don't think that's possible. Second best solution would be to let the user play the song directly in a browser.
I had some luck with the script below in the past (it's quite old). One would link an audio file thusly:
<a href="download.php?f=recording/Old_Grey_Horror_-_Franz_Ferdinand_Must_Die.m4a">Download "Franz Ferdinand Must Die"</a>
And the result was usually pretty good. It would most often ask the user where they want to save the file.
Here's the old script:
<?
/**
* This script takes a GET string argument which specifies a filename
* And will spit out the contents of that file as an attachment with the
* appropriate mimetype.
*/
// the file to be downloaded
$file = $_GET['f'];
if (empty($file)) {
die('no file specified');
}
// watch out for sneaky attempts at a parent directory
if (preg_match('#\.\.#', $file)) {
die('no parent directory access permitted');
}
// get the file extension
$ext_pattern = '/\.([0-9a-z]+)$/i';
$num_matches = preg_match($ext_pattern, $file, $matches);
if ($num_matches != 1) {
die('Unable to locate extension, pattern returned ' . $num_matches . ' matches');
}
$extension = $matches[1];
#echo "extension:" . $extension . ' <br>';
$mime_type = get_mime_type($extension);
if (!$mime_type) {
die('no mime type found');
}
// file paths are interpreted relative to current working directory
if (!file_exists('./' . $file)) {
die('file not found');
}
$filename = basename($file);
#echo 'filename:' . $filename . '<br>';
// output the file to the user
do_download($file, $mime_type, $filename);
die();
function get_mime_type($ext) {
switch (strtolower($ext)) {
case 'mp3':
return 'audio/mpeg';
break;
case 'm4a':
return 'audio/mp4';
break;
default:
die('unrecognized extension, unable to find mime type');
}
} // get_mime_type
function do_download($file, $mime_type, $save_as){
$size=filesize(urldecode($file));
$attachment=(
strpos($HTTP_USER_AGENT,"Mozilla/4")===false // Not Moz4
|| // or
strpos($HTTP_USER_AGENT,"MSIE")!==false) // is IE
? ' attachment;'
: '';
// no idea why those urldecodes are in there.
$content_disposition = "Content-Disposition:" . $attachment . " filename=" . urldecode($save_as);
header($content_disposition);
header("Content-Type: " . $mime_type);
header("Content-Length: $size");
readfile(urldecode($file));
}
?>