Hello,
habe darüber nochmal etwas länger nachgedacht und so ergab sich diese Funktion für den Download für Files. Ich bitte um Diskussion.
<?php ### download.php ###
# Download-Funktion für beliebige Files
#
# Stand: 20100515-0821
#
# Author: Tom, bitworks@online.de
#
# Sinn: Nur dann Download starten, wenn noch keine Nutzlast-Übertragung
# stattgefunden hat. Die Headers dürfen noch nicht gesendet sein!
# Nur dann Download-Headers setzen, wenn das File wirklich lesbar war
# Vermeidung des TOCTOU-Problemes, das bei "if (file_exists())" enstehen würde
# Abfangen der Fehlermeldung von readfile()
#
# Nachteil: Das File muss in den Output-Buffer passen
#
#--------------------------------------------------------------------------------------------------
function download_file($filename)
{
if (!headers_sent())
{
ob_start(); ## neuen Puffer aufmachen
if (false !== ($len = readfile($filename))) ## File in den neuen OB laden und header
{ ## nur bei Erfolg Header ausgeben
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($filename));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . $len);
ob_end_flush(); ## neuen Output-Buffer ausgeben
exit; ## alle anderen OBs werden geschlosen
## und weggeschmissen, Script beendet.
}
else
{
return ob_get_clean(); ## die Fehlermeldung von readfile() ausgeben
}
}
return "Headers already sent";
}
#===================================================================================================
# php main
#===================================================================================================
$error = download_file ('testdatei.txt');
# als Beweis dafür, dass die Fehlermeldung von readfile() wirklich eingefangen wird:
echo "Fehlermeldung: $error ENDE";
?>
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg