Azure与Google Drive对接的可行性及基于ASP.NET Core的Azure部署系统免费文件存储实现方案
当然可以!Azure部署的ASP.NET Core系统完全能对接Google Drive存储用户文件
我刚好做过类似的需求,用来节省Azure Blob存储的成本,这个方案是完全可行的——Google提供了官方的Drive API,能让你的ASP.NET Core应用直接和Google Drive进行文件交互,不管是部署在Azure还是其他平台都能正常工作。下面我分两种常见场景给你讲具体实现步骤:
场景1:将文件存储到应用专属的Google Drive空间(无需用户授权)
这种情况适合所有用户上传的文件都存在你自己管理的Google Drive文件夹里,不需要用户登录Google账号,用服务账号来实现:
1. 前期在Google Cloud Console的准备
- 登录Google Cloud Console,新建一个项目,搜索并启用「Google Drive API」。
- 创建一个服务账号:在「IAM与管理员」→「服务账号」页面点击「创建服务账号」,填写信息后,点击「创建并继续」,权限可以暂时选「项目→编辑者」(后续可以缩小权限),完成创建。
- 给服务账号生成密钥:进入刚创建的服务账号详情页,切换到「密钥」标签,点击「添加密钥」→「创建新密钥」,选择JSON格式,下载密钥文件(务必妥善保管,不要提交到代码仓库)。
- 共享Drive文件夹给服务账号:在你的Google Drive里新建一个文件夹,右键→「共享」,输入服务账号的邮箱(就是密钥文件里的
client_email字段值),给它「编辑」权限,保存。记住这个文件夹的ID(浏览器地址栏里folders/后面的字符串)。
2. 在ASP.NET Core项目中集成
- 安装必要的NuGet包:
Install-Package Google.Apis.Drive.v3 Install-Package Google.Apis.Auth - 编写一个Google Drive存储服务类,封装上传/下载逻辑:
using Google.Apis.Drive.v3; using Google.Apis.Auth.OAuth2; using System.IO; using System.Threading.Tasks; using System.Collections.Generic; public class GoogleDriveStorageService { private readonly DriveService _driveService; private readonly string _rootFolderId; public GoogleDriveStorageService(string serviceAccountJson, string rootFolderId) { // 从JSON密钥初始化凭据,只请求必要的Drive文件权限 var credential = GoogleCredential.FromJson(serviceAccountJson) .CreateScoped(DriveService.Scope.DriveFile); _driveService = new DriveService(new() { HttpClientInitializer = credential, ApplicationName = "你的ASP.NET Core应用名称" }); _rootFolderId = rootFolderId; } // 上传文件到指定文件夹 public async Task<string> UploadUserFileAsync(Stream fileStream, string fileName, string contentType) { var fileMetadata = new Google.Apis.Drive.v3.Data.File() { Name = fileName, Parents = new List<string> { _rootFolderId } }; // 创建上传请求,只返回文件ID var uploadRequest = _driveService.Files.Create(fileMetadata, fileStream, contentType); uploadRequest.Fields = "id"; var uploadResponse = await uploadRequest.UploadAsync(); if (uploadResponse.Status != Google.Apis.Upload.UploadStatus.Completed) { throw uploadResponse.Exception; } // 返回上传后的文件ID,用于后续下载或删除 return uploadRequest.ResponseBody.Id; } // 可选:添加下载、删除文件的方法 public async Task<Stream> DownloadFileAsync(string fileId) { var stream = new MemoryStream(); var downloadRequest = _driveService.Files.Get(fileId); await downloadRequest.DownloadAsync(stream); stream.Position = 0; return stream; } } - 在Program.cs中注册服务,从配置读取密钥和文件夹ID:
var builder = WebApplication.CreateBuilder(args); // 从配置获取参数(建议用Azure应用设置,不要硬编码) var serviceAccountJson = builder.Configuration["GoogleDrive:ServiceAccountJson"]; var rootFolderId = builder.Configuration["GoogleDrive:RootFolderId"]; builder.Services.AddSingleton<GoogleDriveStorageService>(_ => new GoogleDriveStorageService(serviceAccountJson, rootFolderId)); // ... 其他中间件配置
3. Azure部署的注意事项
- 不要把密钥文件打包到部署包,而是把JSON内容粘贴到Azure App Service的应用设置里(配置→应用设置→新建应用设置,键为
GoogleDrive:ServiceAccountJson,值为JSON的内容),文件夹ID同理。 - 确保Azure App Service的出站网络能访问Google API(默认是允许的,如果你的App Service在虚拟网络中,需要配置出站规则放行)。
- 大文件上传需要用分块上传逻辑,上面的示例适合100MB以内的文件,超过的话要调用
CreateMediaUpload并设置分块大小。
场景2:让用户将文件存储到自己的Google Drive(需要用户授权)
如果想让用户上传的文件存在他们自己的Google Drive里,需要用OAuth 2.0让用户授权你的应用访问他们的Drive:
1. Google Cloud Console配置
- 同样启用Google Drive API,然后创建「OAuth 2.0客户端ID」,类型选「Web应用」,填写授权回调URL(比如你的Azure App Service地址 +
/signin-google)。 - 记住生成的Client ID和Client Secret。
2. ASP.NET Core集成OAuth
- 安装NuGet包:
Install-Package Google.Apis.Auth.AspNetCore3 - 在Program.cs中配置Google OAuth登录:
builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie() .AddGoogle(options => { options.ClientId = builder.Configuration["GoogleAuth:ClientId"]; options.ClientSecret = builder.Configuration["GoogleAuth:ClientSecret"]; // 请求Drive文件操作的权限 options.Scope.Add(DriveService.Scope.DriveFile); // 保存用户的凭据到Cookie,方便后续调用API options.SaveTokens = true; }); - 在控制器中获取用户的凭据并创建DriveService:
[Authorize] public class UserDriveController : Controller { private readonly IConfiguration _configuration; private readonly IHttpContextAccessor _httpContextAccessor; public UserDriveController(IConfiguration configuration, IHttpContextAccessor httpContextAccessor) { _configuration = configuration; _httpContextAccessor = httpContextAccessor; } public async Task<IActionResult> UploadUserFile(IFormFile file) { // 从HttpContext获取用户的Google访问令牌 var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token"); var credential = new UserCredential(new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = new ClientSecrets { ClientId = _configuration["GoogleAuth:ClientId"], ClientSecret = _configuration["GoogleAuth:ClientSecret"] } }), "user", new TokenResponse { AccessToken = accessToken }); var driveService = new DriveService(new() { HttpClientInitializer = credential, ApplicationName = "你的应用名称" }); // 接下来的上传逻辑和场景1类似,只是文件会存在用户自己的Drive里 var fileMetadata = new Google.Apis.Drive.v3.Data.File() { Name = file.FileName }; using var stream = file.OpenReadStream(); var uploadRequest = driveService.Files.Create(fileMetadata, stream, file.ContentType); await uploadRequest.UploadAsync(); return Ok(new { FileId = uploadRequest.ResponseBody.Id }); } }
总结
两种方案都能满足你的需求:
- 如果是系统统一存储用户文件,选场景1(服务账号),无需用户操作,管理更方便;
- 如果要让用户自己管理上传的文件,选场景2(OAuth授权),更符合用户的数据归属需求。
部署到Azure后,只要配置好凭据,就能正常运行,完全可以替代Azure存储来保存用户上传的文件,节省成本。
内容的提问来源于stack exchange,提问作者ido_sternheim




