la butto là..

credo che:

header("Content-Length: " . strlen($buffer));

sia sbagliata...

strlen non ti restituisce niente se non è una stringa.. e tu gli passi un buffer...

se vuoi la dimensione, mi viene in mente questo sistema, se ce ne sono altri, tanto meglio, però intanto prova così:

ob_start();
echo $buffer;
$dimensione = ob_get_length();
ob_end_clean();

Ora in $dimensione hai la dimensione giusta....

Metti queste 4 righe prima di:
header("Content-Length: " . $dimensione);

e vedrai che và... (il resto del codice non lo toccare però... .. in sostanza diventa così:

Codice PHP:
<?    
    $filename 
$_GET["filename"];
    
$buffer file_get_contents($filename);

    
/* Force download dialog... */
    
header("Content-Type: application/force-download");
    
header("Content-Type: application/octet-stream");
    
header("Content-Type: application/download");

    
/* Don't allow caching... */
    
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");

    
/* Set data type, size and filename */
    
header("Content-Type: application/octet-stream");
    
header("Content-Transfer-Encoding: binary");
//========================================================
ob_start();
echo 
$buffer;
$dimensione ob_get_length();
ob_end_clean();
header("Content-Length: " $dimensione);
//========================================================
    
header("Content-Disposition: attachment; filename=$filename");

    
/* Send our file... */
    
echo $buffer
?>