You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:PHP使用Microsoft Graph API v2实现OneDrive文件上传下载

PHP MS Graph v2 实现OneDrive文件存储检索方案

核心代码实现(基于GraphServiceClient)

1. 登录授权引导

多租户场景下,使用AuthorizationCodeContext即可,租户ID设为common(支持所有Azure AD租户用户登录),无需指定具体租户ID。

use Microsoft\Graph\GraphServiceClient;
use Microsoft\Kiota\Authentication\Oauth2\AuthorizationCodeContext;

$clientId = '你的应用ID';
$clientSecret = '你的应用密钥';
$redirectUri = '你的回调地址';

// 构造授权URL(未登录时跳转)
if (!isset($_GET['code']) && (!isset($_SESSION['ms_graph_token']) || $_SESSION['ms_graph_token']['expires_at'] <= time())) {
    $authUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=$clientId&response_type=code&redirect_uri=" . urlencode($redirectUri) . "&scope=Files.ReadWrite.All offline_access";
    header("Location: $authUrl");
    exit;
}

2. Token存储与复用

回调获取token后存入Session,后续请求先检查token有效性,未过期则直接复用,过期则用refresh_token刷新或重新授权。无需自定义InMemoryAccessTokenCache,Session管理更适配Web场景。

// 回调时获取并存储token
if (isset($_GET['code'])) {
    $authContext = new AuthorizationCodeContext(
        'https://login.microsoftonline.com/common/oauth2/v2.0/token',
        $clientId,
        $clientSecret,
        $redirectUri,
        $_GET['code']
    );
    $token = $authContext->getToken();
    $_SESSION['ms_graph_token'] = [
        'access_token' => $token->getAccessToken(),
        'refresh_token' => $token->getRefreshToken(),
        'expires_at' => time() + $token->getExpiresIn()
    ];
}

// 初始化已授权的Graph客户端
$authContext = new AuthorizationCodeContext(
    'https://login.microsoftonline.com/common/oauth2/v2.0/token',
    $clientId,
    $clientSecret,
    $redirectUri
);
$authContext->setToken(new \Microsoft\Kiota\Authentication\Oauth2\OAuth2Token(
    $_SESSION['ms_graph_token']['access_token'],
    'Bearer',
    $_SESSION['ms_graph_token']['expires_at'] - time(),
    $_SESSION['ms_graph_token']['refresh_token']
));
$graphClient = new GraphServiceClient($authContext);

3. 文件元数据存储

上传前先在自有数据库插入元数据,获取唯一ID用于后续关联OneDrive文件:

// 示例:PDO操作数据库
$pdo = new PDO('mysql:host=localhost;dbname=你的数据库', '用户名', '密码');
$stmt = $pdo->prepare("INSERT INTO file_metadata (user_id, original_name, upload_time) VALUES (?, ?, NOW())");
$stmt->execute([$_SESSION['user_id'], $_FILES['file']['name']]);
$fileUniqueId = $pdo->lastInsertId(); // 获取数据库唯一ID

4. 大文件上传(兼容小文件)

LargeFileUploadTask支持所有文件大小,小于3MB的文件会自动采用简单上传模式,无需额外处理:

use Microsoft\Graph\Generated\Drives\Item\Items\Item\CreateUploadSession\CreateUploadSessionPostRequestBody;
use Microsoft\Graph\Core\Tasks\LargeFileUploadTask;

// 准备上传会话请求
$uploadSessionRequestBody = new CreateUploadSessionPostRequestBody();
$uploadSessionRequestBody->setItem([
    '@microsoft.graph.conflictBehavior' => 'replace',
    'name' => $fileUniqueId . '_' . $_FILES['file']['name'] // 用数据库唯一ID命名,方便检索
]);

// 创建上传会话并执行上传
$driveItem = $graphClient->me()->drive()->root()->itemWithPath('应用存储目录/' . $fileUniqueId . '_' . $_FILES['file']['name'])->createUploadSession()->post($uploadSessionRequestBody);
$uploadTask = new LargeFileUploadTask($graphClient, $driveItem, fopen($_FILES['file']['tmp_name'], 'r'), $_FILES['file']['size']);
$uploadResult = $uploadTask->upload();

// 上传成功后更新数据库,关联OneDrive文件ID
if ($uploadResult->isSuccessful()) {
    $stmt = $pdo->prepare("UPDATE file_metadata SET onedrive_file_id = ? WHERE id = ?");
    $stmt->execute([$uploadResult->getResponse()->getId(), $fileUniqueId]);
}

关键问题解答

  • 租户ID是否必须?:多租户应用使用common作为租户标识即可,无需指定具体租户ID,支持任意Azure AD租户用户登录。
  • Session已有token是否跳过授权?:需要先检查token是否过期,未过期可直接复用;若过期,优先用refresh_token刷新,失败则重新引导授权。
  • 自定义InMemoryAccessTokenCache是否必需?:不需要,Web应用直接通过Session管理token更直观,无需额外实现缓存类。
  • 小文件上传影响?:LargeFileUploadTask兼容所有文件大小,小于3MB的文件会自动适配简单上传流程,无需特殊处理。

内容的提问来源于stack exchange,提问作者Peter Brand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:18:29