Основная проблема, как отмечено в комментарии, заключается в том, что вы сохраняете весь файл в памяти перед отправкой, что может привести к очень долгому ожиданию в зависимости от размера файла. Что вы предпочитаете делать, так это выводить буфер при чтении сегментов в память, например, в 1024-байтовых блоках.
Вы могли бы попробовать что-то более похожее на:
if ($file = fopen($filename, 'rb')) {
while(!feof($file)) {
print(fread($file, 1024*8));
flush();
}
fclose($file);
}
Который не будет пытаться прочитать весь файл перед выводом, а будет выводить блоки файла, когда они считываются в выходной буфер.