PHP 在 echo 后发送 header 的问题

2018-08-19 11:53:42 +08:00
 SomeBottle

之前玩 PHP 尝试在 echo 后发送 Header,但是直接写在一起是没法送出去头的..

根据网上的方法我把 echo 和 header 丢到了 ob 缓冲区里,就像下面这个图一样..

本地 phpStudy 环境测试非常成功..但是扔到服务器(Linux - Nginx)上后就出现了发送不出去头的问题, 本来我期待在 echo 执行完后关闭连接转服务端执行的...结果 header 发不出去只会全部执行完再返回数据..

求问我是哪里写错了吗...还是说这种方法已经不可行了,测试 PHP 版本是 5.4...

3991 次点击
所在节点    PHP
16 条回复
bao0541
2018-08-19 12:04:16 +08:00
请注意 header() 必须在任何实际输出之前调用,不管是普通的 HTML 标签,还是文件或 PHP 输出的空行,空格。这是个常见的错误,在通过 include,require,或者其访问其他文件里面的函数的时候,如果在 header()被调用之前,其中有空格或者空行。 同样的问题也存在于单独的 PHP/HTML 文件中。
SomeBottle
2018-08-19 12:07:15 +08:00
@bao0541 我现在的问题就在于不懂为什么会这样,不然早就解决了...前面没有任何输出,我打开全部报错也没有任何报错,这是用于 ajax 请求的一个后端,只有这一句 echo 输出.
chinvo
2018-08-19 12:14:01 +08:00
你第二行 echo 就是输出,header 必须放在任何输出前
batnss
2018-08-19 12:15:17 +08:00
header 2 句放最后试试
SomeBottle
2018-08-19 12:34:07 +08:00
@chinvo 询问一下 session 算输出吗..
@batnss 这样行不通,obflush 直接输出了缓冲区的 echo
NextAccount
2018-08-19 12:50:39 +08:00
@SomeBottle session 本质上是 header set-cookie,所以不算输出。这里的输出指的是 response body 的部分。

我测试了一下 Content-Length 输出成功,但是 Connection 头仍然是 Keep-Alive,这个和 HTTP 服务器配置有关系。

"本来我期待在 echo 执行完后关闭连接转服务端执行的...结果 header 发不出去只会全部执行完再返回数据.." --- 这句话是什么意思?
SomeBottle
2018-08-19 12:54:40 +08:00
@NextAccount 就是如果没有关闭连接就要等待 flush 后的程序执行完才会返回 echo,不过刚刚我在想 fastcgi_finish_request();有没有作用..
chinvo
2018-08-19 13:01:21 +08:00
header 放到 ob_start 之前
chinvo
2018-08-19 13:03:22 +08:00
你现在的写法把 header 包在 ob cache 里面了
SomeBottle
2018-08-19 13:05:15 +08:00
@chinvo 我换了好多 header 的位置还是不行,你提示的这个地方我也试过,只有 Content-Length 被设置了,看来是 http 服务器设置有问题..
NextAccount
2018-08-19 13:08:31 +08:00
@SomeBottle 即使你成功输出 Connection: close 头信息,也并不会关闭当前的 HTTP 连接。你完全可以 有条件的 return 掉不行么?
NextAccount
2018-08-19 13:10:54 +08:00
fastcgi_finish_request() 会结束客户端连接,也许可行。但是后面的代码仍然会执行。
SomeBottle
2018-08-19 13:14:35 +08:00
@NextAccount 我需要的就是继续在服务端执行后面的代码。fastcgi_finish_request 虽然有环境的限制,但是我记得很多网站服务器 PHP 模块都支持 fastcgi 协议
NextAccount
2018-08-19 13:14:38 +08:00
终于明白了楼主的意思。楼主是想要尽快输出,但是有一部分代码在服务器端继续执行。

你有几个选择:

1. fastcgi_finish_request
2. 通过消息系统或者直接 exec 开后台子进程去异步执行。
mrcn
2018-08-19 14:49:22 +08:00
搞个后台队列是最方便的。

header 发送的是 http 头,必须在所有输出之前,就像你必须先拿碗才能装菜一样。
otakustay
2018-08-19 18:14:07 +08:00
如果你想尽快输出内容,那么就别用 Content-Length,用 chunked encoding 输出

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/481127

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX