google drive api v3 认证必须用 oauth 2.0,服务账号不可行;本地开发应使用“桌面应用”凭据调用 authorizeasync 启动浏览器授权并缓存 token.json,需启用 drive api、设对 redirect_uri 和作用域(如 drive.file)。

Google Drive API v3 的认证必须用 OAuth 2.0,服务账号行不通
Google Drive API 不允许服务账号(Service Account)直接写入普通用户网盘——哪怕你用 Subject 模拟用户,也必须确保该用户已显式授权服务账号访问其 https://www.googleapis.com/auth/drive.file 或更宽权限。本地开发最稳妥的方式是用 OAuth 2.0 用户凭据:调用 GoogleWebAuthorizationBroker.AuthorizeAsync 启动本地浏览器授权流程,首次运行会生成 token.json 缓存凭据。
容易踩的坑:
- 忘记在 Google Cloud Console 中为项目启用 Drive API(不止是创建凭据)
- OAuth 凭据类型选成“服务账号密钥”或“API 密钥”,必须选“桌面应用”或“其他”
- 未将
redirect_uri设为urn:ietf:wg:oauth:2.0:oob或http://localhost(取决于客户端库版本) - 作用域写错,例如用了
drive.readonly却想上传,应至少用https://www.googleapis.com/auth/drive.file
上传文件需区分简单上传和分块上传
小文件(Files.Create + MediaUpload),大文件必须用分块上传(Files.Create with ResumableUpload)。C# 客户端库会自动选择,但你要主动控制 FileSize 和 SupportedUploadKinds 行为。
关键实操点:
- 构造
Google.Apis.Drive.v3.Data.File对象时,Parents字段传new List<string> { "folder_id" }</string>才能指定目标文件夹;留空则上传到根目录 - 设置
Body后,必须调用FilesResource.CreateRequest.UploadAsync()(不是ExecuteAsync) - 上传前检查
FileMetaData.MimeType,如不确定可调用MimeMapping.GetMimeMapping("file.ext")(需引用System.Web) - 上传流必须是可重读的(
stream.CanSeek == true),否则分块上传会失败;临时用new MemoryStream(File.ReadAllBytes(path))最保险
上传后获取文件 ID 和分享链接要分两步
Files.Create 返回的 Google.Apis.Drive.v3.Data.File 对象只含基础字段(Id, Name, WebViewLink 等),但 WebViewLink 默认不可公开访问。若需外链,必须额外调用 Permissions.Create。
常见错误场景:
- 直接打印
file.WebViewLink,结果打开提示“您无权访问此内容”——因为权限未开放 - 调用
Permissions.Create时传了type: "user"却没填emailAddress,应改用type: "anyone"+role: "reader" - 误以为
file.Id是短链接,实际它是长字符串 ID(如1aBcDeFgHiJkLmNoPqRsTuVwXyZ),拼接https://drive.google.com/file/d/{id}/view才是标准链接
调试 403/404 错误优先查 scopes 和 folder ID 权限
上传失败时,GoogleApiException.Error.Code 为 403 多半是权限问题;404 则大概率是目标文件夹 ID 不存在或当前用户无访问权(哪怕文件夹是自己创建的,也要确认是否被移入“共享云端硬盘”且你有编辑权限)。
快速定位建议:
- 用
Files.List+Q = "'folder_id' in parents"测试能否列出该文件夹下的内容 - 捕获异常后打印
e.Error.Message和e.Error.Errors[0].Reason,常见值如insufficientPermissions、notFound、appNotAuthorized - 确认 OAuth token 缓存(
token.json)未过期,且刷新逻辑已正确配置(GoogleWebAuthorizationBroker.AuthorizeAsync内部会处理) - 如果上传到“共享云端硬盘”(Shared Drive),必须改用
supportsAllDrives = true并用corpora = "allDrives"查询
真正麻烦的是权限继承和共享云端硬盘的混合场景——比如文件夹在共享云端硬盘里,但你的 OAuth 账号只是成员而非管理员,这时即使 ID 正确,上传也会静默失败或返回 404。这种 case 得先用 Drives.Get 和 Permissions.List 交叉验证上下文权限,不能只盯着上传代码本身。











