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

PHP实现Azure文件上传至Google Drive 解决Untitled文件名问题

解决Google Drive API上传文件命名异常及Azure URL上传需求问题

先给你拆解核心问题:你遇到的Untitled.pdf命名问题,本质是因为用了uploadType=media的上传方式——这种方式只传文件二进制内容,不带任何元数据(比如文件名),所以Drive会自动分配默认名称。要解决这个,得改用multipart类型上传,同时传递文件内容和元数据。另外针对你要从Azure URL直接上传、设置文件公开权限的需求,我给你整理了完整的修正方案:


一、修复文件命名为Untitled的问题 + 支持Azure URL上传

下面是重构后的uploadFile函数,既解决命名问题,又能直接从Azure URL拉取文件上传:

function uploadFile($credentials, $azureFileUrl, $fileName) {
    global $GAPIS;
    
    // 1. 从Azure URL获取文件内容(如果Azure文件带SAS权限,直接传带SAS的完整URL即可)
    $fileContent = file_get_contents($azureFileUrl);
    if ($fileContent === false) {
        throw new Exception("无法从Azure地址获取文件,请检查URL有效性");
    }
    
    // 2. 构造文件元数据(指定文件名、类型等)
    $metadata = json_encode([
        'title' => $fileName,
        'mimeType' => 'application/pdf' // 可根据实际文件类型调整,或自动检测MIME
    ]);
    
    // 3. 构造多部分请求的边界标识
    $boundary = uniqid();
    $delimiter = "--" . $boundary;
    $closeDelimiter = "--" . $boundary . "--";
    
    // 4. 拼接多部分请求体:元数据块 + 文件内容块
    $body = $delimiter . "\r\n"
          . "Content-Type: application/json\r\n\r\n"
          . $metadata . "\r\n"
          . $delimiter . "\r\n"
          . "Content-Type: application/pdf\r\n\r\n"
          . $fileContent . "\r\n"
          . $closeDelimiter;
    
    // 5. 初始化cURL请求
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $GAPIS . 'upload/drive/v2/files?uploadType=multipart');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . getAccessToken($credentials),
        'Content-Type: multipart/related; boundary=' . $boundary,
        'Content-Length: ' . strlen($body)
    ]);
    
    $postResult = curl_exec($ch);
    if (curl_errno($ch)) {
        throw new Exception("上传请求出错:" . curl_error($ch));
    }
    curl_close($ch);
    
    $response = json_decode($postResult, true);
    if (isset($response['error'])) {
        throw new Exception("Drive API返回错误:" . $response['error']['message']);
    }
    
    // 6. 上传完成后自动设置文件为公开可读
    setFilePublic($credentials, $response['id']);
    
    // 返回可存入数据库的Drive文件信息
    return [
        'fileId' => $response['id'],
        'publicUrl' => $response['alternateLink'],
        'fileName' => $response['title']
    ];
}

二、添加设置文件公开权限的函数

上面的函数里调用了setFilePublic,专门用来实现你的“公开访问权限”需求:

function setFilePublic($credentials, $fileId) {
    global $GAPIS;
    
    $permissionData = json_encode([
        'type' => 'anyone', // 允许任何人访问
        'role' => 'reader'  // 只读权限,避免被修改
    ]);
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $GAPIS . 'drive/v2/files/' . $fileId . '/permissions');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $permissionData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Authorization: Bearer ' . getAccessToken($credentials),
        'Content-Type: application/json'
    ]);
    
    $result = curl_exec($ch);
    if (curl_errno($ch)) {
        throw new Exception("设置权限出错:" . curl_error($ch));
    }
    curl_close($ch);
    
    $response = json_decode($result, true);
    if (isset($response['error'])) {
        throw new Exception("权限设置API返回错误:" . $response['error']['message']);
    }
    
    return true;
}

三、额外优化建议

  1. Azure文件获取的备选方案:如果服务器禁用了file_get_contents,可以改用cURL拉取Azure文件:
function getAzureFileContent($azureUrl) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $azureUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $content = curl_exec($ch);
    curl_close($ch);
    return $content;
}

然后在uploadFile里替换$fileContent = getAzureFileContent($azureFileUrl);即可。

  1. 回到Google Client库的简化方案:其实你最初用的Google官方Client库更易维护,也能直接实现Azure URL上传,代码更简洁:
$client->setAccessToken($_SESSION['accessToken']);
$service = new Google_DriveService($client);

// 示例:循环处理多个Azure文件
$azureFiles = [
    "Invoice-2024-05.pdf" => "https://your-azure-storage.blob.core.windows.net/container/invoice.pdf",
    "Report-Q2.pdf" => "https://your-azure-storage.blob.core.windows.net/container/report.pdf"
];

foreach ($azureFiles as $fileName => $azureUrl) {
    $fileContent = file_get_contents($azureUrl);
    
    $file = new Google_DriveFile();
    $file->setTitle($fileName);
    $file->setMimeType('application/pdf');
    
    // 上传文件
    $createdFile = $service->files->insert(
        $file,
        ['data' => $fileContent, 'mimeType' => 'application/pdf']
    );
    
    // 设置公开权限
    $permission = new Google_Permission();
    $permission->setType('anyone');
    $permission->setRole('reader');
    $service->permissions->insert($createdFile->getId(), $permission);
    
    // 把公开URL存入数据库
    $publicUrl = $createdFile->getAlternateLink();
    // 这里执行你的数据库插入逻辑
}

四、调用示例

$credentials = getStoredCredentials($STORE_PATH);
if (!$credentials) {
    requestAuthCode();
}

try {
    $azureUrl = "https://your-azure-storage.blob.core.windows.net/container/your-file.pdf";
    $fileName = "客户合同-2024.pdf";
    $driveFileInfo = uploadFile($credentials, $azureUrl, $fileName);
    
    // 将$driveFileInfo['publicUrl']存入数据库
    echo "文件上传成功,公开访问地址:" . $driveFileInfo['publicUrl'];
} catch (Exception $e) {
    echo "操作失败:" . $e->getMessage();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:09:01