我正在尝试使用 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();
}
}
}
我遇到了同样的问题并找到了解决方案。关键点是:您必须创建一个没有 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()
它有效。希望对你有帮助。
参考https://developers.google.com/drive/v3/reference/files#resource-representations,可以看到
shared
不是可写字段。如果你仔细想想,这是完全有道理的。您可以通过添加新权限来共享文件,并且可以通过读取共享属性来检查文件是否已共享。但是,除了实际共享文件之外,说文件已共享是没有任何意义的。
在代码中它看起来像这样
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();
尝试更改远程文件中的字段,并重写此文件可能会引发安全异常,如下所示的异常。 但这不是你问题的解决方案。 如果您想通过电子邮件将文件共享到另一个谷歌帐户,您可以通过使用应用程序的服务帐户重新实现授权来实现授权,并添加所需的电子邮件作为文件的所有者。
我也在做同样的事情。我的目标是以编程方式与我的 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""")
我强烈认为该错误与权限直接相关。请检查此格式!
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();
}
}
}
我遇到了类似的错误。这是从首先获取文件然后尝试对该文件运行更新开始的。文件的 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。