我的知识记录

BOM头导致headers already sent错误_PHP输出控制

很多站长遇到网站页面顶部有一行空白、验证码图片显示叉号、登录后session不生效、接口返回JSON解析失败等问题,排查半天找不到原因,最后发现是文件有BOM头。BOM头是不可见字符,在编辑器中看不到,但在PHP执行时会作为输出发送到浏览器,导致header()、session_start()、setcookie()等函数失败(因为HTTP头必须在任何输出之前发送)。本文系统讲解BOM头的检测和去除方法,覆盖主流编辑器(Notepad++、VSCode、Sublime、Dreamweaver)和批量脚本(PHP、Python、Linux命令、PowerShell),帮助彻底解决BOM头问题。

PHP脚本批量去除网站BOM头(适合虚拟主机用户)。把以下脚本保存为remove_bom.php,上传到网站根目录,浏览器访问http://域名/remove_bom.php,脚本会自动扫描当前目录及子目录下的所有PHP、HTML、CSS、JS、TXT文件,去除BOM头并显示处理结果。代码:<?php header('Content-Type: text/html; charset=utf-8'); $dir = __DIR__; $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); $count = 0; foreach ($iterator as $file) { if ($file->isFile() && in_array(strtolower($file->getExtension()), ['php','html','htm','css','js','txt','xml','json'])) { $f = fopen($file->getPathname(), 'r'); $bom = fread($f, 3); fclose($f); if ($bom == pack('CCC', 0xEF, 0xBB, 0xBF)) { $content = file_get_contents($file->getPathname()); $content = substr($content, 3); file_put_contents($file->getPathname(), $content); echo '已去除BOM: ' . $file->getPathname() . '
'; $count++; } } } echo '
处理完成,共去除 ' . $count . ' 个文件的BOM头。'; ?>。使用后务必删除此脚本,避免被他人访问。

Linux命令批量去除BOM头(适合有SSH权限的用户)。方法一:find命令配合sed,扫描当前目录及子目录下所有PHP文件,去除开头三个字节:find . -type f -name "*.php" -exec sed -i '1s/^xefxbbxbf//' {} ;。把*.php改为*.html、*.css、*.js等处理其他类型。方法二:用find配合vim:find . -type f ( -name "*.php" -o -name "*.html" -o -name "*.js" -o -name "*.css" ) -exec vim -c "set nobomb" -c "wq" {} ;。方法三:用dos2unix工具(部分系统自带):dos2unix *.php。dos2unix会同时转换换行符和去除BOM。执行前先备份文件,批量操作有风险。

Python脚本批量去除BOM头(适合本地开发环境)。代码:# -*- coding: utf-8 -*- import os def remove_bom(path): count = 0 for root, dirs, files in os.walk(path): for f in files: if f.lower().endswith(('.php', '.html', '.htm', '.css', '.js', '.txt', '.xml', '.json')): filepath = os.path.join(root, f) with open(filepath, 'rb') as fp: data = fp.read() if data[:3] == b'xefxbbxbf': with open(filepath, 'wb') as fp: fp.write(data[3:]) print(f'已去除: {filepath}') count += 1 print(f'完成,共处理{count}个文件') if __name__ == '__main__': remove_bom('.')。保存为remove_bom.py,在网站目录下运行python remove_bom.py。Python3环境下运行,处理前备份文件。

VSCode去除BOM头。打开文件后,点击右下角状态栏的编码显示(如「UTF-8 with BOM」),在弹出菜单中选择「Save with Encoding」(通过编码保存),然后选择「UTF-8」(不带BOM的选项),保存后BOM头去除。设置默认保存为无BOM:点击「文件」-「首选项」-「设置」,搜索「files.encoding」,设置为utf8;搜索「files.showByteOrderMark」,设置为false(不显示BOM标记,即默认不添加BOM)。VSCode默认新建UTF-8文件是不带BOM的,但打开带BOM的文件保存时会保留BOM,需要手动转为无BOM。

Notepad++去除BOM头。打开文件后,点击菜单「编码」-「转为UTF-8无BOM编码」,然后保存文件。底部状态栏会从「UTF-8-BOM」变为「UTF-8」。批量去除多个文件:在Notepad++中打开所有需要处理的文件,点击「编码」-「转为UTF-8无BOM编码」,然后按Ctrl+Shift+S全部保存。注意Notepad++的「编码」菜单中有「使用UTF-8无BOM编码」和「转为UTF-8无BOM编码」两个选项,「使用」是设置编辑器显示编码不改变文件内容,「转为」才是真正转换文件编码去除BOM头,一定要选「转为」。设置默认保存为无BOM:「设置」-「首选项」-「新建」,编码选择UTF-8,不勾选「应用到打开的ANSI文件」。

BOM头与编码乱码的关系。BOM头本身不会导致中文乱码,乱码通常是因为文件编码和页面声明的编码不一致(文件是GBK但页面声明UTF-8,或反之)。但BOM头会加剧编码问题——带BOM头的UTF-8文件被当作GBK解析时,BOM头三个字节会显示为乱码字符(锘?)。解决乱码的根本方法是统一所有文件编码为UTF-8无BOM,同时在页面head中声明,PHP文件设置header('Content-Type: text/html; charset=utf-8'),数据库连接设置SET NAMES utf8。编码统一后,BOM头和乱码问题都能解决。

防止BOM头的最佳实践。一是统一团队编辑器设置,所有开发者设置默认保存为UTF-8无BOM,在编辑器配置或团队规范中明确。二是代码提交前检查,Git可以配置pre-commit钩子检测BOM头,SVN可以用pre-commit脚本。三是网站程序上线前用批量脚本扫描一次,确保没有BOM头。四是从官方渠道下载程序,很多第三方修改版可能带BOM头。五是PHP项目中在入口文件开头用ob_start()开启输出缓冲,可以缓冲BOM头输出,避免header失败,但这只是临时方案,根本解决还是去除BOM头。六是模板文件(HTML、CSS、JS)也要检查,不只是PHP文件。

BOM头导致session_start()失败的完整排查。报错「Warning: session_start(): Cannot send session cookie - headers already sent by (output started at /path/config.php:1)」,行号是1,说明config.php文件开头有输出。用编辑器打开config.php,查看编码是否是UTF-8-BOM,如果是,转为UTF-8无BOM保存。同时检查config.php被哪些文件include,那些文件也不能有BOM头。如果多个文件都有BOM头,用批量脚本一次性处理。处理后清除浏览器缓存和服务器缓存(如果有OPcache),重新测试。如果session仍然失败,检查php.ini中output_buffering是否开启,开启输出缓冲可以缓冲BOM头,但建议去除BOM头而不是依赖缓冲。

站长反馈:「网站页面顶部一直有空白,验证码也不显示,排查了两天才发现是BOM头的问题,用Notepad++批量转为UTF-8无BOM后全部正常了」「下载的网站程序安装后乱码,按文中PHP批量脚本跑了一遍,去除了几十个文件的BOM头,页面立刻正常,虚拟主机用户用这个脚本太方便了」。

操作提示:遇到页面顶部空白、验证码不显示、session/cookie失败、JSON解析失败,先检查报错行号,如果是行号1基本就是BOM头。单个文件用编辑器「转为UTF-8无BOM」处理,注意选「转为」不是「使用」。整个网站用批量脚本处理(PHP脚本适合虚拟主机,Python/PowerShell适合本地,find/sed适合Linux服务器)。处理前务必备份文件,批量操作有风险。处理后清除浏览器缓存和OPcache,重新测试。

BOM头导致headers already sent错误_PHP输出控制

标签:

更新时间:2026-08-27 11:56:03

上一篇:虚拟主机屏蔽脚本请求 UA指南_不误封百度蜘蛛的写法

下一篇:宝塔面板账号密码忘记重置方法:命令行重置教程_宝塔面板_服务器运维_配置教程