求助: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
相关产品推荐
相关产品推荐

