readfile 遇到 Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 185679872 bytes)
异常代码:
function download($name, $path) {
// 不限制脚本的最大执行时间,避免在指定的时间内文件未下载完成。
set_time_limit(0);
$file_name = urldecode($name);
$file_path = urldecode($path);
$file_name = iconv("utf-8", "gb2312//IGNORE", $file_name);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-type:text/html;charset=utf-8");
header('Content-Disposition: attachment; filename=' . $file_name);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
readfile($file_path);
}
download($_GET['file_name'], $_GET['file_path']);
首先可以使用 fread
逐步读取,对于大文件进度比较慢:
function download($name, $path) {
// 不限制脚本的最大执行时间,避免在指定的时间内文件未下载完成。
set_time_limit(0);
$file_name = urldecode($name);
$file_path = urldecode($path);
$file_name = iconv("utf-8", "gb2312//IGNORE", $file_name);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-type:text/html;charset=utf-8");
header('Content-Disposition: attachment; filename=' . $file_name);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
// readfile($filePath);
ob_start();
$fp = fopen($filePath, "r+");
$buffer = 1024 * 1024 * 4; // 4m
while (! feof($fp)) {
$file_data = fread($fp, $buffer);
echo $file_data;
ob_flush();
flush();
// 可以进行限速
// sleep(1);
}
ob_end_clean();
fclode($fp);
}
download($_GET['file_name'], $_GET['file_path']);
查看官方手册,手册中指出:
readfile
读取文件并写入到输出缓冲
readfile() 自身不会导致任何内存问题。如果出现内存不足的错误,使用
ob_get_level()
确保输出缓存已经关闭
最后调整为:
function download($name, $path) {
// 不限制脚本的最大执行时间,避免在指定的时间内文件未下载完成。
set_time_limit(0);
$file_name = urldecode($name);
$file_path = urldecode($path);
$file_name = iconv("utf-8", "gb2312//IGNORE", $file_name);
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-type:text/html;charset=utf-8");
header('Content-Disposition: attachment; filename=' . $file_name);
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
if (ob_get_level()) {
ob_end_flush();
}
readfile($file_path);
}
download($_GET['file_name'], $_GET['file_path']);