0

我将下面的示例代码放在一起,使用 Google 的 dot net google api 客户端库示例附带的一些帮助代码。

问题:即使我将一个文件上传到拥有此服务帐户的 Google 帐户,它也没有列出任何文件信息。

当我尝试使用 oauth 授权做同样的事情时,我得到了预期的结果(我在这个页面上做到了:https ://developers.google.com/drive/v2/reference/files/list )。

也许范围界定有问题;有任何想法吗?

我记录所有 http 请求和响应的尝试完全失败了。谷歌客户端库似乎是基于每个 api 登录的,我看不到任何谷歌驱动器。当我尝试使用 log4net 和 dotnetopenauth 时也没有做任何事情(谷歌的客户端库使用 dot net open auth)。

这是代码:

using System;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Authentication.OAuth2;
using Google.Apis.Authentication.OAuth2.DotNetOpenAuth;
using Google.Apis.Drive.v2;
using Google.Apis.Util;
using Google.Apis.Services;

namespace Drive.ServiceAccount
{
    class Program
    {

        static Program()
        {
//
            //ApplicationContext.RegisterLogger(new Log4NetLogger());
            log4net.Config.XmlConfigurator.Configure();          
        }

        private const string SERVICE_ACCOUNT_EMAIL = "<blablalba>@developer.gserviceaccount.com";
        private const string SERVICE_ACCOUNT_PKCS12_FILE_PATH = @"<blablalba>-privatekey.p12";

        /// <summary>
        /// Build a Drive service object authorized with the service account.
        /// </summary>
        /// <returns>Drive service object.</returns>
        static DriveService BuildService()
        {
            X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret",
                X509KeyStorageFlags.Exportable);

            var _client = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
            {
                ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
                Scope = DriveService.Scopes.Drive.GetStringValue(),
            };
            var auth = new OAuth2Authenticator<AssertionFlowClient>(_client, AssertionFlowClient.GetState);

            var service = new DriveService(new BaseClientService.Initializer()
            {
                Authenticator = auth,
                ApplicationName = "Drive API Sample",
            });

            return service;
        }

        static void Main(string[] args)
        {
            var _driveService = BuildService();

            var _files = _driveService.Files.List().Execute();

            foreach (var _file in _files.Items)
            {
                Console.WriteLine(_file.Id);
            }

            Console.WriteLine("Done");

            Console.ReadLine();
        }

    }
}

感谢 Robadob 纠正了我对服务帐户的误解。这是一些工作代码(只是上面所有其他内容的主要方法):

static void Main(string[] args)
{

    String _newFileName = Guid.NewGuid().ToString() + ".xml";

    new XDocument( new XElement("root", new XElement("someNode", "someValue")))
        .Save(_newFileName);

    Console.WriteLine("New file saved locally with name {0}.", _newFileName);

    var _driveService = BuildService();

    // upload the file:

    //var uploadStream = 
    //    new System.IO.FileStream(_newFileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);

    byte[] byteArray = System.IO.File.ReadAllBytes(_newFileName);
    MemoryStream _byteStream = new MemoryStream(byteArray);

    var insert = _driveService.Files.Insert(new Google.Apis.Drive.v2.Data.File
    {
        Title = _newFileName,
    }, _byteStream, "text/xml");

    Task _uploadTask = insert.UploadAsync();

    _uploadTask.ContinueWith(t => Console.WriteLine("Upload Task Completed"),TaskContinuationOptions.OnlyOnRanToCompletion);
    //

    try
    {
        _uploadTask.Wait();
    }
    catch (AggregateException _ex)
    {
        foreach (Exception ex in _ex.Flatten().InnerExceptions)
        {
            Console.WriteLine(ex.Message);
        }
    }

    Console.WriteLine("Reading files");

    var _files = _driveService.Files.List();


    foreach (var _file in _files.Execute().Items)
    {
        Console.WriteLine(_file.Id);
    }

    Console.WriteLine("Done");

    Console.ReadLine();
}
4

1 回答 1

0

由于它是一个服务帐户,我认为它没有自己的“Google Drive”,服务帐户的存在是为了代表用户行事。

要“模拟”您希望列出其文件的用户,您需要prn在生成访问令牌时传递一个参数;

如果您向下滚动到“附加索赔”,可以在此处找到详细信息; https://developers.google.com/accounts/docs/OAuth2ServiceAccount#formingclaimset

似乎您可以通过此设置用户;

        var _client = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
        {
            ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
            Scope = DriveService.Scopes.Drive.GetStringValue(),
            ServiceAccountUser = "Name@Company.com"
        };

如果您希望记录 HTTP 交互,我发现Fiddler比其他方法更容易设置。

于 2013-08-06T12:33:36.277 回答