PHP逐行输出数据并解决两种常见缓冲问题

本文介绍如何利用PHP的输出缓冲区解决百万数据单页面输出及文件下载时浏览器卡死的问题,通过逐步输出的方式减轻服务器与客户端的压力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.遇到问题

不知你们有没有碰到过这样两种情况:

  1. 老板要你将数据库中所有的数据在浏览器中展示出来,因为需要对比数据,老板要求是不能使用分页,那么好了,输出个1000条数据直接循环打印出来没问题,但是数据如果是几百万条呢?浏览器直接卡死,等你离开座位出去喝了杯咖啡,上了个厕所,和前台mm聊了个天,回来发现浏览器已经“程序未响应”了,你该怎么办?
  2. 老板让你改进一下网站的下载链接,要求直接鼠标左击就下载文件(某些文件类型,直接左击会打开这个文件,很多网站会提示你“右键另存为”),你用了header函数和readfile函数轻松实现了这个功能,但是上线后发现如果文件过大浏览器依旧会卡死,这次老板要请你喝咖啡了,你该怎么办?
好吧,如果你碰到了以上两种情况,或者你将来可能会面临这样的问题,你可以mark一下,以便下次快速解决。
2.原理

言归正传。

下面隆重推出PHP输出控制之输出缓冲区

首先,试一下下面代码的效果
<?php  
if (ob_get_level() == 0){ ob_start() }else{ exit(0);};//开始缓冲  
  
for ($i = 0; $i<10; $i++){  
    echo "Line to show.\n<br />";//不直接输出,先存入缓冲区中  
    ob_flush();//将缓冲区的数据输出出来  
    flush();//将缓冲区的数据输出出来  
    sleep(2);//暂停两秒  
}  
  
echo "Done.";  
  
ob_end_flush();//关闭并清理缓冲区  
想不到PHP也能实现这种延迟加载的功能吧,是不是很牛X的感觉。

原理的话就是PHP在输出数据前先将数据放进缓冲(Buffer)里,等待需要时我们再将缓冲的数据输出出来,注意一下这里不要跟缓存(Cache)混淆。

这样做的好处一方面可以实现类似延迟加载的炫酷效果,一方面也能够降低服务器和客户端的压力,不然输出大数据时就会出现内存不够用的情况。

注:ob_flush()和flush()在用途上都是刷出缓冲区数据,但是官方建议配套使用因为虽然在大部分WebServer下只用ob_flush()就能刷出缓冲,但是在某些情况下如apache中有时需要调用flush()才行,所以为了你代码的可移植性,建议看到ob_flush()立马在后面加上flush()。

既然知道了原理,我们来解决开头提到的两个问题。

3.解决百万数据单页面输出卡死的问题
<?php  
ob_start();  
$data = [1,2,3,4,5,6,7,8,9,10];//实际数据更多,为方便距离假设浏览器一次输出10条会卡死  
$per = 3;//每次输出3条,可以改成1000   
  
for ($i = 0;$i < count($data); $i+= $per){  
    for($j = $i; $j < $i + $per && $j <count($data); $j++){  
        echo $data[$j];  
    }  
    ob_flush();  
    flush();  
    sleep(2);  
}  
  
echo "Done.";  
  
ob_end_flush();

4.解决header实现文件下载时文件过大导致卡死的问题

<?php  
header('Content-type: application/txt');//输出类型  
ob_start();  
  
$data = "qwertyuioasdfghjkl";//文件内容,file_get_contents($file)  
$per = 15;//每次输出15个字符,可以改成1000或更大   
  
  
for ($i = 0;$i < strlen($data); $i+= $per){  
    for($j = $i; $j < $i + $per && $j <strlen($data); $j++){  
        echo $data[$j];  
    }  
    sleep(2);  
    ob_flush();  
    flush();  
}  
  
  
echo "Done.";   
      
ob_end_flush();  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值