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

Laravel/核心PHP实现登录用户传文件至管理员OneDrive方案咨询

实现客户端用户上传文件至管理员OneDrive(Laravel/核心PHP方案)

先解决你之前Microsoft Graph API失败的常见坑

  • 必须注册机密客户端应用,并申请应用权限(而非委派权限),比如Files.ReadWrite.All,且需要管理员同意该权限
  • 确保使用**客户端凭证流(Client Credentials Flow)**获取token,而非用户授权流
  • 访问管理员OneDrive必须使用/users/{admin-id}/drive端点,而非/me/drive或/drives/root(后者针对应用自身存储)
  • 提前通过Graph Explorer获取管理员的用户ID/主体名,以及目标文件夹的路径(或ID)

Laravel 实现步骤

1. 安装依赖

composer require microsoftgraph/msgraph-sdk-php

2. 配置环境变量(.env)

MS_GRAPH_TENANT_ID=你的Azure租户ID
MS_GRAPH_CLIENT_ID=你的客户端ID
MS_GRAPH_CLIENT_SECRET=你的客户端密钥
ADMIN_USER_ID=管理员的用户ID或邮箱(如admin@yourdomain.com)
ADMIN_UPLOAD_FOLDER=管理员OneDrive内的目标文件夹名(如"用户上传文件")

3. 编写上传逻辑(控制器示例)

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Microsoft\Graph\Graph;

class OneDriveUploadController extends Controller
{
    // 已登录用户上传文件至管理员OneDrive
    public function upload(Request $request)
    {
        // 验证上传文件
        $request->validate([
            'file' => 'required|file|max:51200', // 限制50M以内
        ]);

        $uploadedFile = $request->file('file');
        $fileName = $uploadedFile->getClientOriginalName();
        $fileContent = fopen($uploadedFile->getRealPath(), 'r');
        $fileSize = $uploadedFile->getSize();

        // 获取Graph API访问token
        $token = $this->getAccessToken();
        if (!$token) {
            return response()->json(['error' => '获取API授权失败'], 500);
        }

        $graph = new Graph();
        $graph->setAccessToken($token);

        try {
            // 创建文件上传会话
            $uploadSessionUrl = "/users/" . env('ADMIN_USER_ID') . "/drive/root:/".env('ADMIN_UPLOAD_FOLDER')."/$fileName:/createUploadSession";
            $sessionResponse = $graph->createRequest("POST", $uploadSessionUrl)
                ->addHeaders(['Content-Type' => 'application/json'])
                ->attachBody([
                    'item' => [
                        '@microsoft.graph.conflictBehavior' => 'rename' // 重复文件自动重命名
                    ]
                ])
                ->execute();

            $uploadUrl = $sessionResponse->getUploadUrl();

            // 上传文件内容
            $uploadResponse = $graph->createRequest("PUT", $uploadUrl)
                ->addHeaders([
                    'Content-Length' => $fileSize,
                    'Content-Range' => "bytes 0-".($fileSize-1)."/".$fileSize
                ])
                ->attachBody($fileContent)
                ->execute();

            fclose($fileContent);

            return response()->json([
                'message' => '文件上传成功',
                'file_id' => $uploadResponse->getId(),
                'file_name' => $uploadResponse->getName()
            ]);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    // 获取客户端凭证模式的access token
    private function getAccessToken()
    {
        $tokenEndpoint = "https://login.microsoftonline.com/" . env('MS_GRAPH_TENANT_ID') . "/oauth2/v2.0/token";
        $postData = http_build_query([
            'grant_type' => 'client_credentials',
            'client_id' => env('MS_GRAPH_CLIENT_ID'),
            'client_secret' => env('MS_GRAPH_CLIENT_SECRET'),
            'scope' => 'https://graph.microsoft.com/.default'
        ]);

        $ch = curl_init($tokenEndpoint);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        $response = curl_exec($ch);
        curl_close($ch);

        $tokenData = json_decode($response, true);
        return $tokenData['access_token'] ?? null;
    }

    // 示例:获取管理员上传文件夹内的文件列表
    public function listFiles()
    {
        $token = $this->getAccessToken();
        if (!$token) {
            return response()->json(['error' => '获取API授权失败'], 500);
        }

        $graph = new Graph();
        $graph->setAccessToken($token);

        $files = $graph->createRequest("GET", "/users/" . env('ADMIN_USER_ID') . "/drive/root:/".env('ADMIN_UPLOAD_FOLDER').":/children")
            ->execute();

        return response()->json($files->getArray());
    }
}

4. 路由配置(routes/api.php)

// 仅允许已登录用户访问
Route::post('/upload-to-admin-onedrive', [OneDriveUploadController::class, 'upload'])->middleware('auth:sanctum');
Route::get('/admin-onedrive-files', [OneDriveUploadController::class, 'listFiles'])->middleware('auth:sanctum');

核心PHP 实现步骤

1. 封装Token获取函数

<?php
function getGraphAccessToken($tenantId, $clientId, $clientSecret) {
    $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token";
    $postFields = http_build_query([
        'grant_type' => 'client_credentials',
        'client_id' => $clientId,
        'client_secret' => $clientSecret,
        'scope' => 'https://graph.microsoft.com/.default'
    ]);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $tokenUrl);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $response = curl_exec($ch);
    curl_close($ch);

    $tokenData = json_decode($response, true);
    return $tokenData['access_token'] ?? null;
}

2. 处理用户上传并同步至管理员OneDrive

<?php
// 确保用户已登录(此处需自行实现登录校验逻辑)
session_start();
if (!isset($_SESSION['user_id'])) {
    die("请先登录");
}

// 处理文件上传
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
    // 配置参数
    $tenantId = "你的Azure租户ID";
    $clientId = "你的客户端ID";
    $clientSecret = "你的客户端密钥";
    $adminUserId = "管理员邮箱或用户ID";
    $targetFolder = "用户上传文件";

    // 获取Token
    $token = getGraphAccessToken($tenantId, $clientId, $clientSecret);
    if (!$token) {
        die("获取API授权失败");
    }

    $fileName = $_FILES['file']['name'];
    $filePath = $_FILES['file']['tmp_name'];
    $fileSize = $_FILES['file']['size'];

    // 创建上传会话
    $sessionUrl = "https://graph.microsoft.com/v1.0/users/$adminUserId/drive/root:/$targetFolder/$fileName:/createUploadSession";
    $sessionHeaders = [
        "Authorization: Bearer $token",
        "Content-Type: application/json"
    ];
    $sessionBody = json_encode([
        'item' => ['@microsoft.graph.conflictBehavior' => 'rename']
    ]);

    $ch = curl_init($sessionUrl);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $sessionHeaders);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $sessionBody);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $sessionResponse = curl_exec($ch);
    curl_close($ch);

    $sessionData = json_decode($sessionResponse, true);
    $uploadUrl = $sessionData['uploadUrl'] ?? null;
    if (!$uploadUrl) {
        die("创建上传会话失败:" . json_encode($sessionData));
    }

    // 上传文件内容
    $fileContent = fopen($filePath, 'r');
    $uploadHeaders = [
        "Content-Length: $fileSize",
        "Content-Range: bytes 0-".($fileSize-1)."/$fileSize"
    ];

    $ch = curl_init($uploadUrl);
    curl_setopt($ch, CURLOPT_PUT, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $uploadHeaders);
    curl_setopt($ch, CURLOPT_INFILE, $fileContent);
    curl_setopt($ch, CURLOPT_INFILESIZE, $fileSize);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $uploadResponse = curl_exec($ch);
    curl_close($ch);
    fclose($fileContent);

    $uploadResult = json_decode($uploadResponse, true);
    if (isset($uploadResult['id'])) {
        echo "文件上传成功,文件ID:" . $uploadResult['id'];
    } else {
        echo "上传失败:" . json_encode($uploadResult);
    }
} else {
    echo "文件上传出错,错误码:" . $_FILES['file']['error'];
}

3. 示例:获取管理员OneDrive目标文件夹的文件列表

<?php
function listAdminOneDriveFiles($token, $adminUserId, $targetFolder) {
    $listUrl = "https://graph.microsoft.com/v1.0/users/$adminUserId/drive/root:/$targetFolder:/children";
    $headers = ["Authorization: Bearer $token"];

    $ch = curl_init($listUrl);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

// 使用示例
$token = getGraphAccessToken("你的租户ID", "你的客户端ID", "你的客户端密钥");
$files = listAdminOneDriveFiles($token, "管理员邮箱", "用户上传文件");
print_r($files);

内容的提问来源于stack exchange,提问作者Avinash Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 06:45:58