passthru输出图片时必须提前设置content-type,否则浏览器无法识别二进制流,导致乱码或下载失败;需确保header()在任何输出前调用,禁用bom,严格校验用户输入并防止命令注入。

passthru 输出图片时 Content-Type 必须提前设置
浏览器不会自动识别 passthru 输出的二进制流,必须在调用前用 header() 明确声明类型,否则会显示乱码或下载失败。常见错误是把 header() 放在 passthru() 后面,或中间有空格/输出导致 headers already sent 报错。
- 必须在任何 HTML、echo、空白行之前调用
header('Content-Type: image/jpeg') - 检查 PHP 文件是否以 UTF-8 无 BOM 格式保存(BOM 会导致隐式输出)
- 若用 Composer 加载器或框架路由,确认没有前置日志、调试输出或自动
echo - 临时调试可用
headers_sent($file, $line)定位输出源头
passthru 的 $command 参数不能拼接用户输入
直接把 $_GET['file'] 或 $_POST['path'] 拼进 passthru 命令字符串,等于给攻击者开后门。PHP7.4 不会自动过滤,passthru("cat $_GET[file]") 可被构造为 ?file=xxx.jpg; rm -rf /,触发命令注入。
- 只允许白名单内的文件名:用
basename($_GET['file'])+ 严格后缀校验(如in_array(pathinfo($file, PATHINFO_EXTENSION), ['jpg','png','gif'])) - 路径必须限定在指定目录内:用
realpath($user_file)和realpath($allowed_dir)比较前缀,防止../../etc/passwd跳出 - 优先用
fopen()+fpassthru()替代 shell 命令读取本地文件,完全规避命令执行风险 - 若必须调用外部程序(如
convert动态生成缩略图),参数要用escapeshellarg()包裹,且仅限单个文件路径
passthru 在 CLI 和 Web SAPI 下行为不一致
同一个 passthru('ls -l') 在命令行运行能打印结果,在 Apache/Nginx 下却可能没输出或卡住——这不是 bug,而是 SAPI 层对 stdout/stderr 的处理差异导致的。
- Web 环境下,
passthru默认将输出直接刷到响应体;但若命令阻塞(如等待输入、后台挂起),可能造成超时或连接中断 - 避免执行交互式命令(如
read,vim),也不要用&后台运行,Web 进程无法管理子进程生命周期 - 测试时用
passthru('echo "test" && sleep 1')验证是否实时输出;若延迟明显,可能是 output buffering 或 web server 缓存干扰 - 生产环境建议加超时控制:用
proc_open()替代,可设timeout并捕获 stderr
PHP7.4 中 passthru 返回值始终为 void,别指望它返回内容
passthru() 的函数签名是 void passthru(string $command, int &$return_var = ?),它不返回命令输出,也不返回最后一行。试图用 $out = passthru('ls') 接收结果,得到的永远是 null。
- 需要捕获输出?改用
exec()(最后一行)或shell_exec()(完整字符串) - 需要原始二进制流直传浏览器?坚持用
passthru(),但别赋值给变量 - 想同时获取状态码和确保输出已发送?第二个参数
&$return_var是唯一可靠方式,例如:passthru('cat photo.jpg', $code); if ($code !== 0) die('File read failed'); - 注意:即使命令失败(如文件不存在),
passthru仍会尝试输出 stderr,若未重定向,可能污染二进制流 → 建议加2>/dev/null或用proc_open分离流
passthru 把命令的 stderr(比如“Permission denied”)也原样吐给了浏览器,导致图片头部损坏,浏览器打不开。这种问题在开发机上可能不显,一上生产就失效——因为权限、路径、SELinux 等环境细节全不同。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











