微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php guzzlehttp 流从 fopen('php://input', "r") 上传到远程端点

如何解决php guzzlehttp 流从 fopen('php://input', "r") 上传到远程端点

我有一个可以在 server1 中接收文件上传PHP 应用程序。该文件预计会非常大。我需要保存文件(在 server1 的本地磁盘中)并将文件发送到 server2 中的另一个 API 端点(目前我尝试使用 guzzle,但答案不是必须的)。

我想最小化加载时间。在我的假设中,可以假设磁盘 I/O(将上传文件写入磁盘)可以忽略不计(因为网络是瓶颈)。

这是我对加载时间的假设(串行):

start |----------uploading to server1----------|
                                                |----------uploading to server2----------| end

我想通过将不完整的文件上传流式传输到 server2 来缩短加载时间,以便获得此加载时间(并行):

start |----------uploading to server1----------|
       bbb|----------uploading to server2----------| end
where bbb is the buffer read delay

所以我的尝试是尝试使用 PHPfopen('PHP://input',"r"),因为它返回一个流,然后在 guzzle 请求正文中使用该流。

server1 中的代码

<?PHP
require_once("vendor/autoload.PHP");

$length = $_SERVER['CONTENT_LENGTH'];
$client = new \GuzzleHttp\Client();
$fileReader = fopen('PHP://input',"r");
$streamPsr7 =  \GuzzleHttp\Psr7\stream_for($fileReader);
$multipartStreamPsr7 = new \GuzzleHttp\Psr7\MultipartStream([["name"=>"bigfile","contents"=>$streamPsr7]]);
$requestPsr7 = new \GuzzleHttp\Psr7\Request(
    'POST',// method
    'http://xxx.xxx.xxx.xxx/test-stream-upload/upload.PHP?filename=bigfile',// endpoint
    ['Content-Length'=>$length],// header
    $multipartStreamPsr7
);
$response = $client->send($requestPsr7);

var_dump($response->getStatusCode());
var_dump(strval($response->getBody()));

server2 中的代码

if(empty($_GET['filename'])) $_GET['filename'] = 'file';

$fileReader = fopen('PHP://input',"r");
$fileWriter = fopen('data/'.$_GET['filename'],"w+");

while(true) {
    $buffer = fgets($fileReader,4096);
    if (strlen($buffer) == 0) {
        fclose($fileReader);
        fclose($fileWriter);
        return true;
    }

    fwrite($fileWriter,$buffer);
}

但它不起作用。当我检查 server2 请求正文为空时,我收到 408 请求超时。

我的问题:

  • 这种方法(从 PHP://input 流式上传)在 PHP 中是否可行?
  • 如果可能,该怎么做?请给出可重现的 PHP 示例来做到这一点
  • 如果在 PHP 中不可能,那么如何在其他语言/应用程序堆栈中做到这一点?

注意:

  • 我知道它不安全(用户可以为文件编写任何名称,使其对远程代码执行开放等),这仅用于演示/复制目的

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。