代码1、2的功能为实现大文件下载
代码1(有问题)(猜错在哪里)
$fp = @fopen($filePath, 'rb');
if ($fp) {
$file_size = filesize($filePath);
header('content-type:application/octet-stream');
header('Content-Disposition: attachment; filename=' . $fileName);
header('HTTP/1.1 200 OK');
header('Accept-Ranges:bytes');
header('content-length:' . $file_size);
while (!feof($fp)) {
echo fread($fp, 4096);
ob_flush();
}
fclose($fp);
}
代码2(无问题)
$fp = @fopen($filePath, 'rb');
if ($fp) {
$file_size = filesize($filePath);
header('content-type:application/octet-stream');
header('Content-Disposition: attachment; filename=' . $fileName);
header('HTTP/1.1 200 OK');
header('Accept-Ranges:bytes');
header('content-length:' . $file_size);
ob_end_clean();
ob_start();
while (!feof($fp)) {
echo fread($fp, 4096);
ob_flush();
flush();
}
ob_end_flush();
fclose($fp);
}
使用代码1下载文件,在 php+apache的环境下测试下载文件无问题,但是在php+nginx的环境下,会出现下载文件内容变多的情况,而且多出的内容为文件首部的一段空白内容
代码2就不会出现此问题,由于代码2中使用了 ob_end_clean(),作用为:删除内部缓冲区的内容,关闭缓冲区,因此不会存在缓冲区中的冗余内容没有被清理而被携带到文件中,造成下载文件不完整
ob的基本原则:
如果ob缓存打开,则echo的数据首先放在ob缓存
如果是header信息,直接放在程序缓存
当页面执行到最后,会把ob缓存的数据放到程序缓存,然后依次返回给浏览器
(分为ob缓存和php程序缓存,后者可以理解为比前者处于更外层)
常见 ob_* 系列函数:
函数 | 说明 |
ob_start | 打开一个输出缓冲区,所有的输出信息不再直接发送到浏览器,而是保存在输出缓冲区里面 |
– | |
ob_clean | 删除内部缓冲区的内容,不关闭缓冲区(不输出) |
ob_end_clean | 删除内部缓冲区的内容,关闭缓冲区(不输出) |
– | |
ob_get_length | 返回内部缓冲区的长度,如果缓冲区未被激活,该函数返回FALSE |
ob_get_level | 返回输出缓冲机制的嵌套级别 |
ob_get_status | 获取输出缓冲区的状态 |
ob_get_contents | 返回缓冲区的内容,不输出 |
– | |
ob_get_clean | 返回内部缓冲区的内容,关闭缓冲区。相当于执行 ob_get_contents() and ob_end_clean() |
ob_get_flush | 返回内部缓冲区的内容,并关闭缓冲区,再释放缓冲区的内容。相当于ob_end_flush()并返回缓冲区内容 |
– | |
flush | 将ob_flush释放出来的内容,以及不在PHP缓冲区中的内容,全部输出至浏览器;刷新内部缓冲区的内容,并输出 |
ob_flush | 发送内部缓冲区的内容到浏览器,删除缓冲区的内容,不关闭缓冲区 |
ob_end_flush | 发送内部缓冲区的内容到浏览器,删除缓冲区的内容,关闭缓冲区 |
原创文章,作者:witersen,如若转载,请注明出处:https://www.witersen.com