PHP ob_get_length 似乎 return 不正确的值
PHP ob_get_length seems to return incorrect value
我有一个函数应该 return JSON 响应客户端,然后在不锁定客户端的情况下继续处理,这似乎工作正常,除非我添加 Content-Length header(我想这样做以确保释放客户端)。
函数为:
function replyAndCarryOn($responseText){
ignore_user_abort(true);//stop apache killing php
ob_start();//start buffer output
echo $responseText;
session_write_close();//close session file on server side to avoid blocking other requests
header("Content-Encoding: none");
header('Content-Type: application/json; charset=utf-8');
header("Content-Length: ".ob_get_length());
header("Connection: close");
ob_end_flush();
flush();
}
这工作正常,除了 JSON 字符串 return 被截断到浏览器,因为 Content-Length 是错误的。例如下面的字符串
{"result":"AUTH","authList":[{"uid":"Adam","gid":"Users","authid":1}, "uid":"Admin","gid":"Admin","authid":2},{"uid":"George","gid":"Users","authid":3},{"uid":"test","gid":"Users","authid":4}],"id":"Payment"}
将显示为:
{"result":"AUTH","authList":[{"uid":"Adam","gid":"Users","authid":1},{"uid":"Admin","gid":"Admin","authid":2},{"uid":"George","gid":"Users","authid":3},{"uid":"test","gid":"Users","authid":4}],"id":"
我可以将 Content-Length header 留在外面,apache (2.2) 会自动添加 'Transfer-Encoding:"chunked"' header 这似乎有效,但我想要深入了解为什么 ob_get_length 没有 return 我需要的值,我知道如果启用 gzip,它会产生太长的结果,但我看到值是相反的过短。
所以我想知道:
a) 我在获取内容长度时做错了什么?
b) 遗漏它有什么问题吗?
根据@Xyv 的评论,服务器似乎在输出字符串前输出了一个换行符和八个空格,但这不包括在ob_get_length return 中。令人尴尬的是,它原来是一个马车 return 并且在第一个 php 标签之前以某种方式添加了八个空格。
我想我 post 将此作为答案以提高可读性。
也许首先捕获输出,然后生成 headers,然后 body?
对我来说这个例子有效:
<?php
function replyAndCarryOn($responseText){
ignore_user_abort(true);//stop apache killing php
ob_flush( );
ob_start( );//start buffer output
echo $responseText;
session_write_close();//close session file on server side to avoid blocking other requests
header("Content-Encoding: none");
header('Content-Type: application/json; charset=utf-8');
header("Content-Length: ".ob_get_length());
header("Connection: close");
echo ob_get_flush();
flush();
}
replyAndCarryOn( '{"result":"AUTH","authList":[{"uid":"Adam","gid":"Users","authid":1}, "uid":"Admin","gid":"Admin","authid":2},{"uid":"George","gid":"Users","authid":3},{"uid":"test","gid":"Users","authid":4}],"id":"Payment"}' );
?>
更新 重要的是要知道 ob_start()
应该在输出任何 body 之前。缓冲区将丢失此数据,因此它可能不会被计算在内。我不是输出缓冲方面的专家,但请确保将 ob_start
放在脚本的开头,这样就很难(呃)出错。 (所以要小心在初始 <?php
之前放置空格 and/or 制表符)。
我有一个函数应该 return JSON 响应客户端,然后在不锁定客户端的情况下继续处理,这似乎工作正常,除非我添加 Content-Length header(我想这样做以确保释放客户端)。 函数为:
function replyAndCarryOn($responseText){
ignore_user_abort(true);//stop apache killing php
ob_start();//start buffer output
echo $responseText;
session_write_close();//close session file on server side to avoid blocking other requests
header("Content-Encoding: none");
header('Content-Type: application/json; charset=utf-8');
header("Content-Length: ".ob_get_length());
header("Connection: close");
ob_end_flush();
flush();
}
这工作正常,除了 JSON 字符串 return 被截断到浏览器,因为 Content-Length 是错误的。例如下面的字符串
{"result":"AUTH","authList":[{"uid":"Adam","gid":"Users","authid":1}, "uid":"Admin","gid":"Admin","authid":2},{"uid":"George","gid":"Users","authid":3},{"uid":"test","gid":"Users","authid":4}],"id":"Payment"}
将显示为:
{"result":"AUTH","authList":[{"uid":"Adam","gid":"Users","authid":1},{"uid":"Admin","gid":"Admin","authid":2},{"uid":"George","gid":"Users","authid":3},{"uid":"test","gid":"Users","authid":4}],"id":"
我可以将 Content-Length header 留在外面,apache (2.2) 会自动添加 'Transfer-Encoding:"chunked"' header 这似乎有效,但我想要深入了解为什么 ob_get_length 没有 return 我需要的值,我知道如果启用 gzip,它会产生太长的结果,但我看到值是相反的过短。
所以我想知道:
a) 我在获取内容长度时做错了什么?
b) 遗漏它有什么问题吗?
根据@Xyv 的评论,服务器似乎在输出字符串前输出了一个换行符和八个空格,但这不包括在ob_get_length return 中。令人尴尬的是,它原来是一个马车 return 并且在第一个 php 标签之前以某种方式添加了八个空格。
我想我 post 将此作为答案以提高可读性。
也许首先捕获输出,然后生成 headers,然后 body?
对我来说这个例子有效:
<?php
function replyAndCarryOn($responseText){
ignore_user_abort(true);//stop apache killing php
ob_flush( );
ob_start( );//start buffer output
echo $responseText;
session_write_close();//close session file on server side to avoid blocking other requests
header("Content-Encoding: none");
header('Content-Type: application/json; charset=utf-8');
header("Content-Length: ".ob_get_length());
header("Connection: close");
echo ob_get_flush();
flush();
}
replyAndCarryOn( '{"result":"AUTH","authList":[{"uid":"Adam","gid":"Users","authid":1}, "uid":"Admin","gid":"Admin","authid":2},{"uid":"George","gid":"Users","authid":3},{"uid":"test","gid":"Users","authid":4}],"id":"Payment"}' );
?>
更新 重要的是要知道 ob_start()
应该在输出任何 body 之前。缓冲区将丢失此数据,因此它可能不会被计算在内。我不是输出缓冲方面的专家,但请确保将 ob_start
放在脚本的开头,这样就很难(呃)出错。 (所以要小心在初始 <?php
之前放置空格 and/or 制表符)。