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

Symfony 5.4大文件(最大5GB)自动上传至OneDrive实现方案咨询

Symfony 5.4 自动上传大文件到OneDrive实现指南

一、OneDrive API授权配置

  • 登录Azure门户,注册新应用程序(账号类型选「任何组织目录中的账户和个人Microsoft账户」)
  • 在应用「API权限」中添加Files.ReadWrite.All(应用权限)和offline_access,完成管理员同意
  • 生成客户端密码(Client Secret),记录好Client ID、Client Secret
  • 获取Refresh Token:执行以下curl命令替换占位符获取长期有效token
    curl -X POST https://login.microsoftonline.com/common/oauth2/v2.0/token \
    -d "client_id=YOUR_CLIENT_ID" \
    -d "scope=https://graph.microsoft.com/.default offline_access" \
    -d "client_secret=YOUR_CLIENT_SECRET" \
    -d "grant_type=client_credentials"
    
    从返回结果中提取refresh_token

二、安装依赖

在Symfony项目中安装Microsoft Graph SDK简化API调用:

composer require microsoft/microsoft-graph

也可直接使用Symfony自带的HttpClient组件,无需额外SDK。

三、大文件分片上传逻辑

5GB文件需用分片上传会话实现,步骤如下:

  1. 创建上传会话:向OneDrive API请求生成会话URL
  2. 分片上传:将本地文件分割为5MB-10MB的块,逐个上传到会话URL
  3. 完成上传:所有块上传后发送合并请求,生成完整文件

四、编写Symfony控制台命令

创建独立命令执行上传任务:

// src/Command/UploadBackupToOneDriveCommand.php
namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Microsoft\Graph\Graph;

class UploadBackupToOneDriveCommand extends Command
{
    protected static $defaultName = 'app:upload-backup-to-onedrive';
    private $clientId;
    private $clientSecret;
    private $refreshToken;

    public function __construct(string $clientId, string $clientSecret, string $refreshToken)
    {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
        $this->refreshToken = $refreshToken;
        parent::__construct();
    }

    protected function configure()
    {
        $this->addArgument('backup-file', InputArgument::REQUIRED, '备份zip文件路径');
        $this->addArgument('onedrive-path', InputArgument::OPTIONAL, 'OneDrive目标路径', '/Backups/');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $backupFile = $input->getArgument('backup-file');
        $onedrivePath = $input->getArgument('onedrive-path');
        $fileName = basename($backupFile);
        $fileSize = filesize($backupFile);

        // 初始化Graph客户端
        $graph = new Graph();
        $graph->setAccessToken($this->getAccessToken());

        // 1. 创建上传会话
        $uploadSession = $graph->createRequest("POST", "/me/drive/root:{$onedrivePath}{$fileName}:/createUploadSession")
            ->attachBody(['item' => ['@microsoft.graph.conflictBehavior' => 'replace']])
            ->execute()->getBody();
        $uploadUrl = $uploadSession['uploadUrl'];

        // 2. 分片上传
        $chunkSize = 5 * 1024 * 1024; // 5MB分片
        $handle = fopen($backupFile, 'rb');
        $offset = 0;

        while ($offset < $fileSize) {
            $end = min($offset + $chunkSize - 1, $fileSize - 1);
            $content = fread($handle, $chunkSize);

            $graph->createRequest("PUT", $uploadUrl)
                ->addHeaders([
                    'Content-Length' => (string)($end - $offset + 1),
                    'Content-Range' => "bytes {$offset}-{$end}/{$fileSize}"
                ])
                ->attachBody($content)
                ->execute();

            $offset = $end + 1;
            $output->writeln("已上传 {$offset}/{$fileSize} 字节");
        }

        fclose($handle);
        $output->writeln("备份文件 {$fileName} 成功上传至OneDrive");

        return Command::SUCCESS;
    }

    private function getAccessToken(): string
    {
        $tokenEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
        $data = [
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret,
            'refresh_token' => $this->refreshToken,
            'grant_type' => 'refresh_token',
            'scope' => 'https://graph.microsoft.com/.default'
        ];

        $ch = curl_init($tokenEndpoint);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);

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

在services.yaml中配置命令参数:

services:
    App\Command\UploadBackupToOneDriveCommand:
        arguments:
            $clientId: '%env(ONEDRIVE_CLIENT_ID)%'
            $clientSecret: '%env(ONEDRIVE_CLIENT_SECRET)%'
            $refreshToken: '%env(ONEDRIVE_REFRESH_TOKEN)%'

在.env中添加环境变量:

ONEDRIVE_CLIENT_ID=你的客户端ID
ONEDRIVE_CLIENT_SECRET=你的客户端密钥
ONEDRIVE_REFRESH_TOKEN=你的刷新令牌

五、自动执行脚本

通过crontab设置定时任务,示例为每天凌晨2点执行:

0 2 * * * cd /你的Symfony项目路径 && php bin/console app:upload-backup-to-onedrive /备份文件路径/backup.zip

注意事项

  • 分片大小需≥5MB(最后一块除外),避免请求过多
  • 添加重试逻辑处理网络波动,可使用Symfony的RetryHttpClient
  • 集成Monolog记录上传日志,便于排查问题
  • 配置@microsoft.graph.conflictBehavior处理文件冲突(如replace覆盖或rename重命名)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 21:54:14