在PHP5.5+的主体中使用大文件发出POST请求;

在PHP5.5+的主体中使用大文件发出POST请求;,php,post,large-data,Php,Post,Large Data,我需要从PHP应用程序中使用一个API。一个端点接收要作为POST请求主体上载的文件。上传的文件可能相当大(高达25GB)。端点返回带有200ok或其他不同状态代码的简单JSON内容 请求示例可能如下所示: POST /api/upload HTTP/1.1 Host: <hostname> Content-Type: application/octet-stream Content-Length: 26843545600 Connection: close <raw fil

我需要从PHP应用程序中使用一个API。一个端点接收要作为POST请求主体上载的文件。上传的文件可能相当大(高达25GB)。端点返回带有
200ok
或其他不同状态代码的简单JSON内容

请求示例可能如下所示:

POST /api/upload HTTP/1.1
Host: <hostname>
Content-Type: application/octet-stream
Content-Length: 26843545600
Connection: close

<raw file data up to 25 GB>
POST/api/upload HTTP/1.1
主持人:
内容类型:应用程序/八位字节流
内容长度:26843545600
连接:关闭
基本上,我需要编写一个方法,在不杀死服务器的情况下执行这样的请求

我试图找到任何合理的实现,但据我所见,cURL和non-cURL(
stream\u context\u create
)方法都需要字符串请求体,这可能会耗尽服务器内存


有没有简单的方法不用写就可以做到这一点?

由于没有更好的选择,我选择了默认的解决方案

下面是实用程序函数的完整源代码,该函数将以低内存消耗执行HTTP请求。作为
数据
参数,它可以接受
字符串
数组
和对象

用法示例:

$file = new SplFileObject('/path/to/file', 'rb');
$contents = request('https://example.com/api/upload', 'POST', $file, $headers);
if ($headers[0] == 'HTTP/1.1 200 OK') {
    print $contents;
}

由于找不到更好的选项,我选择了默认的解决方案

下面是实用程序函数的完整源代码,该函数将以低内存消耗执行HTTP请求。作为
数据
参数,它可以接受
字符串
数组
和对象

用法示例:

$file = new SplFileObject('/path/to/file', 'rb');
$contents = request('https://example.com/api/upload', 'POST', $file, $headers);
if ($headers[0] == 'HTTP/1.1 200 OK') {
    print $contents;
}

打开一个流,然后将您的文件分成小块输入到该流。您不能使用ftp吗?@MarcB是否可以将其与
stream\u context\u create(['http'])
,而不是使用发送/解析头等重新实现协议ᵈˑ在什么意义上?一旦你有了一个流,它基本上就变成了一个文件句柄,你可以使用
fwrite()
,所以你可以用你需要的任何头设置http流,然后进入一个循环
,而($chunk=fread($bigfile\u handle,$max\u chunk\u size)){fwrite($stream\u handle,$chunk);
打开一个流,然后将您的文件分成小块送入该流。您能不能不使用ftp?@MarcB是否可以将其与
流\u上下文\u创建(['http'])
相结合,而不使用发送/解析头等重新实现协议?@ᵈˑ在什么意义上?一旦你有了一个流,它基本上就变成了一个文件句柄,你可以使用
fwrite()
,所以你可以用你需要的任何头设置http流,然后进入一个循环
,而($chunk=fread($bigfile\u handle,$max\u chunk\u size)){fwrite($stream\u handle,$chunk);
谢谢分享。为什么要在检查OK状态时硬编码HTTP版本(例如:
$headers[0]==“HTTP/1.1 200 OK”
)。既然有多个版本,那么解析字符串并提取响应代码不是更好吗?顺便说一句,您可能会使用
==
@belletJuice,我已经提供了此代码作为示例。当然,您可以添加对第一个响应头的更高级解析,以正确获取协议版本和响应状态。关于
==
,我认为这并不重要,因为如果比较非空字符串,严格相同的比较不会给出不同的结果。感谢分享。为什么要在检查OK状态时硬编码HTTP版本(例如:
$headers[0]==“HTTP/1.1 200 OK”
)。既然有多个版本,那么解析字符串并提取响应代码不是更好吗?顺便说一句,您可能会使用
==
@belletJuice,我已经提供了此代码作为示例。当然,您可以添加对第一个响应头的更高级解析,以正确获取协议版本和响应状态。关于
==
,我认为这并不重要,因为如果比较非空字符串,严格相同的比较不会给出不同的结果。