Pues lo q tines q hacer en este caso es manejar las cabeceras HTTP correspondientes al content-type y otras .. Las cabeceras con PHP las lanzas via la funcion header() ..
Yo uso estas:
En $fichero incas la ruta absoluta del archivo (path y archivo.tal)
Código PHP:
<?php
$nombre_fichero=basename($fichero);
if (strstr($_SERVER['HTTP_USER_AGENT'], 'compatible; MSIE ') !== false &&
strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') === false) {
// IE doesn't properly download attachments. This should work
// pretty well for IE 5.5 SP 1
header("Content-Disposition: inline; filename=\"$nombre_fichero\"");
header("Content-Type: application/octetstream; name=\"$nombre_fichero\"");
header("Content-length:".(string)(filesize("$fichero")));
} else {
// Use standard headers for Netscape, Opera, etc.
header("Content-Disposition: attachment; filename=\"$nombre_fichero\"");
header("Content-Type: application/octetstream; name=\"$nombre_fichero\"");
header("Content-length: ".(string)(filesize("$fichero")));
}
readfile("$fichero");
?>
Antes de este código no puede existir naa de HTML (ni en echo "algo" ... o print "algo") . .pues sino te dará problemas de headers enviados bla bla bla ...
En el código se identifica mas o menos el navegador q usa el cliente para enviarle las cabeceras peculiares q acepta cada uno ... (inline y el attachment ..)
En las FAQ's de PHP de este foro (última página) tienes otro ejemplo mas completo q este .. Con cabeceras HTTP extra para darle la funcionalidad de "resume" a tus descargas ..
Un saludo,