In general, you should clean the output buffer before streaming the file, otherwise it may not open. If you're downloading an EXE, the code signing certificate may be corrupted. This may not matter on EXEs that are not code signed, but this is the cleanest method to ensure code signing still is intact by delivering only the file and no 'extra' headers/output.
This is close to another answer, but ob_clean(); has been inserted before the headers.
function serve_file($filepath, $new_filename = null) {
$filename = basename($filepath);
if (!$new_filename) {
$new_filename = $filename;
}
$mime_type = mime_content_type($filepath);
ob_clean();
header('Content-type: ' . $mime_type);
header('Content-Disposition: attachment; filename="' . $new_filename . '"');
readfile($filepath);
}
Usage:
serve_file($url, $filename);
Example:
$url = "example.exe";
$filename = "Example123.exe";
serve_file($url, $filename);