You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#控制台程序获取Google Drive文件下载URL及下载配置咨询

搞定C#控制台程序通过Google Drive API v2下载文件的问题

嘿,我来帮你解决这个下载文件的问题!你现在能访问文件内容但没法下载,主要是没配置好权限,也没针对不同文件类型实现对应的下载逻辑。咱们一步步来:

一、先把Google Cloud项目的关键配置弄对

这是基础,没配置好的话API调用肯定出问题:

  • 启用Google Drive API:登录Google Cloud Console,找到API库,搜索「Google Drive API」然后启用它。
  • 创建桌面应用的OAuth凭据
    1. 进入「凭据」页面,点击「创建凭据」→「OAuth客户端ID」。
    2. 应用类型选「桌面应用」,随便填个名称,创建后下载生成的credentials.json文件,放到你的控制台项目根目录,记得在属性里设置「复制到输出目录」为「始终复制」。
  • 配置OAuth同意屏幕
    1. 切换到「OAuth同意屏幕」页面,选「外部」(个人测试的话选内部也可以)。
    2. 添加API范围:至少勾选https://www.googleapis.com/auth/drive.readonly——要是你以后需要修改文件可以选更宽的drive范围,但下载只读就够了。

二、代码层面实现下载逻辑

你已经有了列文件的方法,现在要加下载的代码。注意要分两种情况:普通文件(比如PDF、图片)和Google原生文件(比如Docs、Sheets),后者得导出成指定格式才能下载。

1. 普通文件的直接下载方法

public static void DownloadFile(DriveService service, Google.Apis.Drive.v2.Data.File file, string savePath)
{
    // 先判断这个文件能不能直接下载
    if (string.IsNullOrEmpty(file.WebContentLink))
    {
        Console.WriteLine($"⚠️ 文件「{file.Title}」不支持直接下载(大概率是Google原生文档)");
        return;
    }

    // 发送请求下载文件
    var downloadRequest = service.HttpClient.GetAsync(file.WebContentLink);
    downloadRequest.Wait();

    // 把流写入本地文件
    using (var stream = downloadRequest.Result.Content.ReadAsStreamAsync().Result)
    {
        using (var localFileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write))
        {
            stream.CopyTo(localFileStream);
            Console.WriteLine($"✅ 文件「{file.Title}」已下载到:{savePath}");
        }
    }
}

2. Google原生文件的导出下载方法

像Google Docs、Sheets这类文件,不能直接下载,得调用导出接口转成常见格式(比如PDF、docx):

public static void ExportGoogleFile(DriveService service, Google.Apis.Drive.v2.Data.File file, string savePath, string exportMimeType)
{
    try
    {
        // 创建导出请求,指定文件ID和目标MIME类型
        var exportRequest = service.Files.Export(file.Id, exportMimeType);
        
        using (var memoryStream = new MemoryStream())
        {
            exportRequest.Download(memoryStream);
            // 把内存流写入本地文件
            using (var localFileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write))
            {
                memoryStream.Position = 0;
                memoryStream.CopyTo(localFileStream);
                Console.WriteLine($"✅ Google文件「{file.Title}」已导出并保存到:{savePath}");
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"❌ 导出文件失败:{ex.Message}");
    }
}

给你列几个常用的导出MIME类型对应:

  • Google Docs → application/vnd.openxmlformats-officedocument.wordprocessingml.document(转docx)
  • Google Sheets → application/vnd.openxmlformats-officedocument.spreadsheetml.sheet(转xlsx)
  • Google Slides → application/vnd.openxmlformats-officedocument.presentationml.presentation(转pptx)
  • 所有原生文件都能转PDF → application/pdf

3. 把列表和下载整合起来

在你的ListFiles方法之后,遍历文件列表,自动判断文件类型并下载:

public static void ListAndDownloadAllFiles(DriveService service, string localDownloadFolder)
{
    var fileList = ListFiles(service);
    
    // 先创建本地下载文件夹
    if (!Directory.Exists(localDownloadFolder))
    {
        Directory.CreateDirectory(localDownloadFolder);
    }

    foreach (var file in fileList.Items)
    {
        // 判断是不是Google原生文件(MIME类型以application/vnd.google-apps.开头)
        bool isGoogleNative = file.MimeType.StartsWith("application/vnd.google-apps.");
        string baseSavePath = Path.Combine(localDownloadFolder, file.Title);

        if (isGoogleNative)
        {
            // 这里演示转成PDF,你可以根据文件类型换对应的MIME类型
            ExportGoogleFile(service, file, $"{baseSavePath}.pdf", "application/pdf");
        }
        else
        {
            // 简单处理重名问题,你可以根据需求优化
            string finalSavePath = baseSavePath;
            int counter = 1;
            while (File.Exists(finalSavePath))
            {
                finalSavePath = $"{baseSavePath}_{counter}";
                counter++;
            }
            DownloadFile(service, file, finalSavePath);
        }
    }
}

三、踩坑排查小贴士

  • 要是碰到权限错误:检查OAuth范围是不是加对了,还有用户第一次授权的时候有没有允许对应的权限。
  • 某些文件下载失败:确认你的授权账号有权限访问这个文件,文件没设成私有或者限制访问。
  • 大文件下载:如果文件超过100MB,建议用分块下载,换成service.Files.Get(file.Id).DownloadWithStatus(stream)来处理,避免内存爆掉。

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

火山引擎 最新活动