如何使用MS Graph PHP SDK V2下载文件?V1迁移遇Stream调用错误
Microsoft Graph PHP SDK V2 文件下载实现
问题背景
在SDK V1中,可通过以下代码直接下载文件到指定路径:
$this->graph->createRequest('GET', '/drives/' . $driveId . '/items/' . $itemId . '/content')->download($path);
升级到V2版本后,原方法不再适用,调用content()->get()返回Http\Promise\FulfilledPromise对象(内部包裹GuzzleHttp\Psr7\Stream),调用getBody()时出现错误:Call to undefined method GuzzleHttp\Psr7\Stream::getBody()。
正确实现方法
方式1:同步下载(代码直观,推荐)
通过wait()解析Promise获取Stream对象,直接写入文件:
$tokenRequestContext = new \Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext( config('graphapi.azure_tenant_id'), config('graphapi.azure_client_id'), config('graphapi.azure_client_secret') ); $graphServiceClient = new \Microsoft\Graph\GraphServiceClient($tokenRequestContext); // 获取文件流(wait()解析Promise得到Stream对象) $fileStream = $graphServiceClient->drives() ->byDriveId(config('graphapi.attachments_drive_id')) ->items() ->byDriveItemId('<drive_item_id>') ->content() ->get() ->wait(); // 小文件:直接写入 file_put_contents('test.txt', $fileStream); // 大文件:使用流复制更高效(避免内存占用过高) // $destStream = fopen('test.txt', 'wb'); // stream_copy_to_stream($fileStream, $destStream); // fclose($destStream);
方式2:异步处理
保留Promise异步逻辑,直接操作Stream对象:
$tokenRequestContext = new \Microsoft\Kiota\Authentication\Oauth\ClientCredentialContext( config('graphapi.azure_tenant_id'), config('graphapi.azure_client_id'), config('graphapi.azure_client_secret') ); $graphServiceClient = new \Microsoft\Graph\GraphServiceClient($tokenRequestContext); $downloadPromise = $graphServiceClient->drives() ->byDriveId(config('graphapi.attachments_drive_id')) ->items() ->byDriveItemId('<drive_item_id>') ->content() ->get(); $downloadPromise->then( function (\GuzzleHttp\Psr7\Stream $fileStream) { // 写入文件 file_put_contents('test.txt', $fileStream); // 大文件推荐用流复制 // $dest = fopen('test.txt', 'wb'); // stream_copy_to_stream($fileStream, $dest); // fclose($dest); }, function (\Exception $e) { echo "下载失败:" . $e->getMessage(); } ); // 异步模式下需确保进程不提前退出,执行wait()阻塞等待完成 // $downloadPromise->wait();
错误原因说明
之前的代码错误在于:Promise解析后的结果本身就是GuzzleHttp\Psr7\Stream类型的响应体流,无需再调用getBody()方法,直接对该Stream对象进行读取或写入操作即可。
内容的提问来源于stack exchange,提问作者Tom Vaughan
相关产品推荐
相关产品推荐

