I had this same problem with ionFiles. First, turn off errors so you don't pipe errors into the download. Use the @ or error_report(0); do to this:
@readfile()
Second, you need to exit after the readfile. Depending on your template system this may or may not help you. In Joomla! if you didn't exit it would parse the website at the header of the file. Here is the code I used for ionFiles download (which now works well):
header("Pragma:no-cache");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: $mtype");
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
if (ini_get('allow_url_fopen')) {
if (extension_loaded('curl')) {
header("Content-Length: " . remoteFileSize($file));
}
}
header("Accept-Ranges: bytes");
@readfile("$file");
/**
* Exit so that Joomla does not output
* the header and footer inside of our
* file.
*/
exit();
$mtype is the mime type and the variable gets assigned from this function:
/**
* Fetches the mime type of a file by
* using the extension and finding it's value in a
* hard-coded array.
*
* @param string $fext
* @return string
*/
function getMimeType($fext) {
# Mime Types
#-------------------------------
$mine_types = array (
# archives
#-------------------------------
'zip' => 'application/zip',
# documents
#-------------------------------
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
# executables
#-------------------------------
'exe' => 'application/octet-stream',
# images
#-------------------------------
'gif' => 'image/gif',
'png' => 'image/png',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
# audio
#-------------------------------
'mp3' => 'audio/mpeg',
'wav' => 'audio/x-wav',
# video
#-------------------------------
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpe' => 'video/mpeg',
'mov' => 'video/quicktime',
'avi' => 'video/x-msvideo'
);
# Find the Mime Type
#-------------------------------
if (@$mine_types[$fext] == '') {
$mtype = '';
# mime type is not set, get from server settings
#-------------------------------
if (function_exists('mime_content_type')) {
$mtype = mime_content_type($file);
}
else
{
$mtype = "application/force-download";
}
}
else
{
# get mime type defined by admin
#-------------------------------
$mtype = $mine_types[$fext];
}
# Return our Type
#-------------------------------
return $mtype;
}
You can use it or not but it does help identify the files for browsers.