最近在使用PHP做企业微信开发,需要在一些特殊的场景下获取数据包,例如用户向企业微信发送消息内容,服务端需要根据消息类型、内容,反馈给用户具体的响应信息。
在这种场景下用到了,PHP的file_get_contents('php://input')和$GLOBALS"HTTP_RAW_POST_DATA"的函数。这里针对两种函数做一个简单的说明。
file_get_contents('php://input')
和 $GLOBALS["HTTP_RAW_POST_DATA"]
都可以用来获取 HTTP POST 请求中的原始数据。
但是它们之间存在一些区别:
- 在 PHP 5.6.0 版本以上,
$GLOBALS["HTTP_RAW_POST_DATA"]
已经被弃用,因为它是不安全且易受攻击的。相反,应该使用file_get_contents('php://input')
。 $GLOBALS["HTTP_RAW_POST_DATA"]
只能在php.ini
文件配置中打开always_populate_raw_post_data
开关时使用,否则它会返回NULL
。file_get_contents('php://input')
可以在任何情况下使用,因为它不依赖于某个特定的配置开关。$GLOBALS["HTTP_RAW_POST_DATA"]
返回的是请求体的原始数据,而file_get_contents('php://input')
返回的是一个包含请求体中所有数据的字符串。因此,如果您想对 POST 数据进行流式处理,您应该使用file_get_contents('php://input')
。
上面内容中,提到了一些流式处理
,这也是本文的重心,接下来就针对流式处理
做一个说明。
流式处理是什么
流式处理是一种逐个处理数据而不是将整个数据集加载到内存中的技术
。它通常用于处理海量数据
或需要持续不断地接收数据
的情况。在流式处理中,数据被分成小块,并逐一处理。
使用流式处理的好处
使用流式处理技术可以减少内存占用
,提高处理效率
,减少处理时间
。因此,流式处理技术经常用于大型文件的读取、数据块的传输、实时数据的处理等场景。例如,在网络编程中,常用的流传输协议包括 TCP 和 UDP,它们可以逐个接收数据而不需要先将所有数据加载到内存中。在 PHP 中,可以使用 fread()
和 fwrite()
函数来进行流式处理。
底层原理实现
流式处理的底层实现原理是通过分批次读取和写入数据实现的。具体来说,流处理是将数据分成较小的块(chunks),并将它们逐一处理。当流数据传输时,数据被分成块,每块都被逐一处理。一次只处理一个块的好处是,可以减少内存占用和处理时间。
在底层实现中,流式处理通常利用缓冲区(buffer)进行。缓冲区是内存中的一块区域,用于存储数据块。当一个数据块读入缓冲区时,程序可以从缓冲区一次读取足够大小的数据进行处理。当缓冲区的数据被处理完后,可以再从输入流中读取下一个数据块,重新填充缓冲区。相同的处理方式可以应用于输出流,即一个数据块被写入缓冲区,并在满足一定条件后同时写入输出流中。
通过流式处理,我们可以有效地减小内存占用量,并帮助应用系统更好地处理大量的数据。
客户端文件上传
客户端传入的数据也是一块一块传递的吗?在一些情况下,客户端传入的数据也是一块一块传递的。这通常发生在客户端向服务器发送大量数据或文件时,为了减少网络带宽的占用和缓解服务器处理的负担,数据会被分成一块一块进行传递。
从客户端到服务器的数据传输通常会被分成多个分组。每个分组都经过网络传输,并在服务器接收到后被组装成完整的数据块。在这个过程中,如果一个数据块损坏或丢失,它可以被重新发送,以保证数据的完整性。
对于 HTTP 协议,它本身是基于请求-响应模型的,客户端向服务器发送请求数据时,请求数据通常是在 TCP/IP 连接中一次性发送的。但是在 WebSocket 协议中,客户端和服务器之间的数据传输是以数据块为单位进行的,即客户端和服务器之间的消息被分成一块一块进行传输,以便更好地处理海量数据或实时数据。