当前位置: 首页 > 知识库问答 >
问题:

无法使用服务帐户将文件插入Google Drive

严兴旺
2023-03-14

我无法使用服务帐户插入google drive。相反,我可以使用相同的服务帐户从google drive下载和更新文件,而不会出现任何问题。我通过转到[我的项目]从特定用户(我们称之为用户“X”)的帐户中创建了服务帐户-

然后,我专门转到用户“X”的MyDrive上的一个文件夹,并将该文件夹与OAuth2的“创建新客户端ID”步骤生成的服务帐户电子邮件地址共享。我确保指定该文件夹的服务帐户权限为“可编辑”。

我已经成功地从该文件夹下载文件,并从该文件夹更新文件。我假设这意味着我的服务号已通过适当的身份验证(其中我成功地获得了一个有一个小时生命的AccessToken)。我已经确定我的范围也是完全访问范围(即https://www.googleapis.com/auth/drive)。

话虽如此,当我尝试插入新文件时,它失败了。我在这里使用了基本模板:https://developers.google.com/drive/v2/reference/files/insert

下面是插入的代码示例

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Util;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Drive.v2.Data;

File body = new File();
body.Title = "Test.pdf";
body.Description = "Why doesn't this work?";
body.MimeType = "application/pdf";
body.Parents = new List<ParentReference>() { new ParentReference() { Id = [ID GOES HERE] } };
using (System.IO.MemoryStream oMemoryStream = new System.IO.MemoryStream())
        {
            string sUploadFileFromDiskPath = @"[PATH TO FILE]";
            using (System.IO.FileStream oFileStream = System.IO.File.OpenRead(sUploadFileFromDiskPath))
            {
                this.BufferedWriteToTarget(oFileStream, oMemoryStream);
                oFileStream.Close();
            }
            FilesResource.InsertMediaUpload insertRequest = ServiceAccount.DriveService.Files.Insert(body, oMemoryStream, body.MimeType); //NOTE: "DriveService" is authenticated (has an AccessToken from the ServiceAccountCredential) in this context with full scope authority
            IUploadProgress progress = insertRequest.Upload();
            File file = insertRequest.ResponseBody; //This is "null" prior to execution because the .Upload() threw an exception
            oMemoryStream.Close();
        }

Upload()调用发生异常,我可以在IUploadProgress对象中看到这个异常。异常显示“找不到给定的头”。堆栈跟踪如下所示:微软的< code >。\r\n位于Microsoft的runtime . compiler services . taskawaiter . throwfornonsuccess(Task Task)。runtime . compiler services . taskawaiter . handlenonsuccess(Task Task)\ r \ n在Microsoft。\r\n位于Microsoft的runtime . compiler services . taskawaiter . validate end(Task Task)。runtime . compiler services . configuredtaskawaitable 1 . configuredtaskawaiter . get result()\ r \ n位于Google . APIs . upload . resumableupload 1。

这是API中的一个bug,还是我遗漏了示例中未包含的内容?

请记住,我已授予服务帐户对我尝试上传到的文件夹的编辑权限,因此这应该不是问题。我不是试图冒充用户,并且不相信在这种情况下我是必需的。

提前感谢您的帮助!

更新:我尝试创建InstalledApplication而不是ServiceAccount。我能够很好地验证已安装的应用程序(对于用户“X”),并获得访问权限

共有1个答案

沈思博
2023-03-14

问题似乎与“BufferedWriteToTarget”方法有关,但我不确定为什么它会导致问题?一旦我更改为使用“ReadAllBytes”方法,如示例中所示,它就工作得很好。

这是我拥有的BufferedWriteToTarget代码:

    private void BufferedWriteToTarget(System.IO.Stream oSourceStream, System.IO.Stream oDestinationStream)
    {
        ////This code copies one stream into another stream.
        const int READ_BUFFER_SIZE = 8192;
        byte[] buffer = new byte[READ_BUFFER_SIZE];
        int n;
        while ((n = oSourceStream.Read(buffer, 0, buffer.Length)) != 0)
            oDestinationStream.Write(buffer, 0, n);
    }

我将保留这篇文章,因为我认为它在我设置服务帐户的步骤方面提供了信息(例如,我在其他任何地方都没有看到任何涉及如何设置服务帐户以及用户帐户中特定文件夹的权限的文档)。

 类似资料:
  • 问题内容: 我正在尝试使用服务帐户在Google日历上创建条目。我真的很接近,但是最后一行是行不通的。我让它运行时得到提示。否则,程序将毫无错误地运行,无论花费多少。 该文件的内容可以发现在这里。在我试图调用方法开始在该文件上的1455线。 问题答案: 我想通了。由于我看不到将服务帐户与API v3一起使用的完整示例,因此我将发布完整的解决方案以供参考。但是,除了实现代码外,还需要做一些事情: 1

  • 我正在工作上传文件在谷歌驱动器与服务帐户,我能够插入文件在谷歌驱动器,但我不能查看该文件在谷歌驱动器。 我是创建abc@gmail.com。用abc@gmail.com创建一个服务帐户。有了P12证书和服务客户端电子邮件id,我可以在驱动器中插入文件。但无法在abc@gmail.com的谷歌驱动器上看到该文件。当fatch从应用程序中的文件列表时,它将显示5个文件,但在我的abc@gmail.co

  • 当试图转移所有权时,我得到以下错误: 下面是我的代码: 该文件夹已成功上传到共享文件夹中的Google Drive(所有者为'email@gmail.com',服务帐户为'editor'),但上传文件的所有者为服务帐户,编辑器为'email@gmail.com'。

  • 我正在构建一个功能,将文件从我的web应用程序上传到我的客户google drive。我不希望应用程序对用户进行身份验证。谁曾经上传过我文件中的任何文件?我想上传到我客户的谷歌硬盘。 我假设服务帐户是用于此目的的帐户。我说得对吗? 当我使用以下代码上传文件时,它会成功上传,但在“我的驱动器”下不可见。然后我添加了一个权限,基本上与我的gmail帐户共享该文件。然后它在“与我共享”部分可见。 我希望

  • 问题内容: 上述代码的结果是: 开启。服务帐户客户ID已在GSuite中使用适当的范围进行了授权。 该服务帐户可用于普通凭据。它仅不适用于委托凭证。 我在我们的域中尝试了不同的API(作用域)和不同的用户。 我有一个同事尝试从头开始编写示例,他得到了同样的东西。 问题答案: 我认为您的问题是,在调用Calendar API 之前,您没有对凭据进行授权,但是我在自己的实现中使用了一些区别 使用以下导

  • 我有一个G套件域,并用域范围的授权打开一个服务号。服务号在项目中也有所有者身份。我启用gmail应用编程接口并添加范围参考(https://developers.google.com/admin-sdk/directory/v1/guides/delegation“将域范围的权限委托给您的服务号”)我也启用不太安全的应用程序设置。 这是我的代码: 但是当我使用这个令牌尝试列出电子邮件时:GETht