使用Google Drive API 3.0服务账户的C#共享盘访问问题排查
问题解决:服务账户操作Google共享盘的配置与代码修正
核心问题分析
- 凭证模拟失效:代码中先创建了带用户模拟的凭证,但随后重新实例化了不带模拟的
ServiceAccountCredential,导致模拟配置被覆盖,服务账户并未以指定用户身份操作。 - 共享盘查询参数缺失:默认的
Files.List接口仅查询服务账户的个人云端硬盘,需额外参数才能访问共享盘内容。 - 文件上传目标错误:未指定共享盘作为父目录时,文件会上传到服务账户的个人盘,无法在个人账号Web UI中显示。
修正步骤与代码
1. 修复DriveService初始化代码
保留正确的用户模拟配置,无需重新创建Credential实例:
private DriveService GetDriveService() { string rootDirectory = Environment.CurrentDirectory; string keyFilePath = Path.Combine(rootDirectory, "mykey.json"); using (var stream = new FileStream(keyFilePath, FileMode.Open, FileAccess.Read)) { var credential = GoogleCredential.FromStream(stream) .CreateScoped(new[] { DriveService.Scope.Drive }) .CreateWithUser("me@domain.com"); // 保留用户模拟配置 return new DriveService(new BaseClientService.Initializer { HttpClientInitializer = credential, ApplicationName = "ServerTools" }); } }
2. 修复文件列表查询(包含共享盘内容)
添加共享盘支持参数,可按需筛选指定共享盘的文件:
public List<string> GetFileList() { var request = _driveService.Files.List(); request.Fields = "nextPageToken, files(id, name)"; // 启用共享盘访问支持 request.IncludeItemsFromAllDrives = true; request.SupportsAllDrives = true; // 可选:仅查询指定共享盘内的文件,替换为你的共享盘ID // request.Q = "'your-shared-drive-id' in parents"; var files = request.Execute().Files; return files?.Select(x => x.Name).ToList() ?? new List<string>(); }
3. 修复文件夹查询(包含共享盘文件夹)
同样添加共享盘支持参数:
private List<string> GetFolders() { var listRequest = _driveService.Files.List(); listRequest.Q = "mimeType='application/vnd.google-apps.folder'"; listRequest.Fields = "nextPageToken, files(id, name)"; // 启用共享盘访问支持 listRequest.IncludeItemsFromAllDrives = true; listRequest.SupportsAllDrives = true; // 可选:仅查询指定共享盘内的文件夹 // listRequest.Q += " and 'your-shared-drive-id' in parents"; var files = listRequest.Execute().Files; return files?.Select(x => x.Name).ToList() ?? new List<string>(); }
4. 上传文件到共享盘的示例代码
必须指定共享盘ID作为父目录,确保文件出现在个人账号Web UI中:
public string UploadFileToSharedDrive(string filePath, string sharedDriveId) { var fileMetadata = new Google.Apis.Drive.v3.Data.File() { Name = Path.GetFileName(filePath), // 指定共享盘为文件父目录 Parents = new List<string> { sharedDriveId } }; using (var stream = new FileStream(filePath, FileMode.Open)) { var request = _driveService.Files.Create(fileMetadata, stream, MimeMapping.GetMimeMapping(filePath)); request.SupportsAllDrives = true; // 必须启用共享盘支持 request.Fields = "id"; var response = request.Upload(); if (response.Status != Google.Apis.Upload.UploadStatus.Completed) { throw response.Exception; } return request.ResponseBody.Id; } }
额外配置验证
- 确认服务账户已被添加为共享盘的管理员权限(你的截图已显示配置正确)。
- 确认域范围委派(Domain-Wide Delegation)已启用,且为服务账户授权了
https://www.googleapis.com/auth/drive或https://www.googleapis.com/auth/drive.file权限。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

