无法使用 Drive API v3 更新 Google Drive 文件 -- 资源正文包含不可直接写入的字段

问题描述 投票:0回答:6

我正在尝试使用 Google Drive API (v3) 更新文档 在 Google 云端硬盘中。

我已阅读此迁移指南: Google Drive API v3 迁移

并对其进行编码以创建一个新的空 File() ,其中包含我要更新的详细信息 然后用它和文件 ID 调用execute()。 但我仍然收到错误。谁能指出我做错了什么? 非常感谢!!

错误:

{
    "code" : 403,
    "errors" : [{
        "domain" : "global",

        "message" : "The resource body includes fields which are not directly writable.",

        "reason" : "fieldNotWritable"
    }],
    "message" : "The resource body includes fields which are not directly writable."
}

代码片段如下:

File newFileDetails = new File();        
FileList result = service2.files().list()
    .setPageSize(10)    
    .setFields("nextPageToken, files(id, name)")
    .execute();

List<File> files = result.getFiles();

if (files == null || files.size() == 0) {

    System.out.println("No files found.");

} else {

   System.out.println("Files:");

   for (File file : files) {

      if (file.getName().equals("first_sheet")) {

         System.out.printf("%s (%s)\n", file.getName(), file.getId());


         newFileDetails.setShared(true);


         service2.files().update(file.getId(), newFileDetails).execute();

      }

   }

}
java google-drive-api
6个回答
6
投票

我遇到了同样的问题并找到了解决方案。关键点是:您必须创建一个没有 Id 的新 File 对象,并在 update() 方法中使用它。这是我的一段代码:

val oldMetadata = service!!.files().get(fileId.id).execute()

val newMetadata = File()
newMetadata.name = oldMetadata.name
newMetadata.parents = oldMetadata.parents
newMetadata.description = idHashPair.toDriveString()

val content = ByteArrayContent("application/octet-stream", fileContent)

val result = service!!.files().update(fileId.id, newMetadata, content).execute()

它有效。希望对你有帮助。


3
投票

参考https://developers.google.com/drive/v3/reference/files#resource-representations,可以看到

shared
不是可写字段。如果你仔细想想,这是完全有道理的。您可以通过添加新权限来共享文件,并且可以通过读取共享属性来检查文件是否已共享。但是,除了实际共享文件之外,说文件已共享是没有任何意义的。


3
投票

在代码中它看起来像这样

Drive service... // your own declared implementation of service
File  file = new File(); //using the com.google.api.services.drive.model package
    // part where you set your data to file like:
file.setName("new name for file");
String fileID = "id of file, which you want to change";
service.files().update(fileID,file).execute();

尝试更改远程文件中的字段,并重写此文件可能会引发安全异常,如下所示的异常。 但这不是你问题的解决方案。 如果您想通过电子邮件将文件共享到另一个谷歌帐户,您可以通过使用应用程序的服务帐户重新实现授权来实现授权,并添加所需的电子邮件作为文件的所有者。


0
投票

我也在做同样的事情。我的目标是以编程方式与我的 Python 代码共享我的文件。

是的,我遇到了同样的错误: “资源体包含不可直接写入的字段”

我通过将虚拟机的服务电子邮件地址(我在 Compute Engine 仪表板上创建)添加到文件的 Editors 解决了这个问题。

然后我在我的虚拟机中运行了这个 Python 代码:

from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials


# Took the json file from my Google Cloud Platform (GCP) → IAM & Admin → Service Accounts:
service_key_file = 'service_key.json'
scope = 'https://www.googleapis.com/auth/drive'

credentials = ServiceAccountCredentials.from_json_keyfile_name(service_key_file, scopes=scope)
driveV3 = build('drive', 'v3', credentials=credentials)

fileId = '1ZP1xZ0WaH8w2yaQTSx99gafNZWawQabcdVW5DSngavQ'  # A spreadsheet file on my GDrive.

newGmailUser = '[email protected]'
permNewBody = {
    'role': 'reader',
    'type': 'user',
    'emailAddress': newGmailUser,
}


driveV3.permissions().create(fileId=fileId, body=permNewBody).execute()
print(f"""The file is now shared with this user:
{newGmailUser}\n
See the file here:
https://docs.google.com/spreadsheets/d/1ZP1xZ0WaH8w2yaQTSx99gafNZWawQabcdVW5DSngavQ""")

0
投票

我强烈认为该错误与权限直接相关。请检查此格式!

import com.google.api.services.drive.model.Permission;

FileList result = service2.files().list()
    .setPageSize(10)
    .setFields("nextPageToken, files(id, name)")
    .execute();

List<File> files = result.getFiles();

if (files == null || files.isEmpty()) {
    System.out.println("No files found.");
} else {
  System.out.println("Files:");

for (File file : files) {
    if (file.getName().equals("first_sheet")) {
        System.out.printf("%s (%s)\n", file.getName(), file.getId());

        Permission permission = new Permission();
        permission.setRole("reader"); 
        permission.setType("anyone");

        service2.permissions().create(file.getId(), permission).execute();
    }
  }
}

0
投票

我遇到了类似的错误。这是从首先获取文件然后尝试对该文件运行更新开始的。文件的 Id 不可写,因此在调用 Update 之前必须将其设置为 null,如下所示:

        var getRequest = driveService.Files.Get(Id);
        var file = await getRequest.ExecuteAsync();
        var id = file.Id;
        file.Id = null; // Must clear Id as that property is not writable.

        var updateRequest = driveService.Files.Update(file, id);
        // Move the file to a folder
        updateRequest.SupportsAllDrives = true;
        updateRequest.AddParents = parentFolderId;
        var movedFile = await updateRequest.ExecuteAsync();

更新请求不会更改文件的 ID。

© www.soinside.com 2019 - 2024. All rights reserved.