【问题标题】:Is there a way of saving a Google Doc so it has the same unique ID as an existing doc?有没有办法保存 Google 文档,使其具有与现有文档相同的唯一 ID?
【发布时间】:2018-05-06 10:40:18
【问题描述】:

我需要创建一个具有特定 ID 的 Google 文档副本 - 不是像 MyDocument 这样的“友好”名称,而是使其在 GoogleSphere 中独一无二的名称 - 像 1x_tfTiA9-b5UwAf3k2fg6y6hyZSYQIvhSNn-saaDs4c 这样的名称。

这就是我想这样做的原因:

我有一份 Google Doc 形式的时事通讯。通过将文档嵌入到<iframe> 元素内的网页中,该时事通讯在网站上发布。除了默认字体大小为 24pt 而不是 11pt 的事实之外,以相同方式发布的通讯的“大字体”版本也是相同的。

我正在尝试自动化大字体版本的制作,但是以这样一种方式,大字体文档的唯一 ID 不会改变,因此嵌入的 <iframe> 仍然有效。

我过去曾尝试使用 Google Apps 脚本例程来创建文档的深层副本,但深层复制功能不能很好地处理图像和表格,因此我永远无法获得完整的副本。如果我可以实现一个“另存为”功能,其中操作数是一个现有的唯一 ID,我认为这会做我想要的。

有人知道我该怎么做吗?

【问题讨论】:

  • 您是否使用过 Drive“高级服务”(又名 Drive REST API)?它提供了对文件属性的更多控制,例如为上传操作设置 id 目标,或给定文件的字节/blob 内容。我自己没有尝试过,否则我会给出答案。
  • 不确定如何从脚本调用 REST API,但我会检查一下。非常感谢。
  • 在高级服务对话框中有一个客户端库。
  • 如果这就是您的意思,则不可能有两个具有相同 file ID 的 Google 文档。可以有任意数量的同名文件。同一个文件实际上可以分配给多个文件夹,但不能有两种不同样式的同一个文件。
  • @SandyGood 我相信 OP 目前有两个 iframe 和两个文件,并且希望自动化更改第二个文件内容的过程,而不是手动复制和粘贴从 A 到 B ,然后增加字体大小。因此,所需的工作流程是“编辑 A,调用函数”,其中函数将 A 导出到具有文档 B 的 id 的文件 - 有效地覆盖以前的 B。这种覆盖意味着网站 C 不需要更新以使用导出的 id ,因为导出的 id 是已知的

标签: iframe google-apps-script google-docs


【解决方案1】:

我对此进行了深入研究,尝试通过多种方式设置文件“大字体”版本的 id:

  1. 通过copy():var copiedFile = Drive.Files.copy(lpFile, spFile.id, options);
    这会产生错误:

    复制请求目前不支持生成的 ID

  2. 通过insert():var newFile = Drive.Files.insert(lpFile, doc.getBlob(), options);
    这会产生错误:

    Google 文档格式不支持生成的 ID

  3. 通过update():Drive.Files.update(lpFile, lpFile.id, doc.getBlob(), options);
    此方法成功地从小打印文件更新“大打印”文件。但是,此特定行使用Document#getBlob() 方法,该方法在Document 的格式和丰富内容方面存在问题。特别是,正如您所提到的,不保留图像和表格(除其他外,如字体更改等)。比较prepost

似乎 - 如果可以找到从文档中导出格式化字节内容的适当方法 - update() 方法最有希望。请注意,Apps Script 客户端库中的update() 方法需要Blob 输入(即doc.getBlob().getBytes() 将不起作用),因此基本限制可能是生成的@987654344 中(缺乏)对丰富格式信息的支持@ 数据。考虑到这一点,我尝试了几种方法从“小字体”文件中获取“格式化”Blob 数据:

  1. 通过Document#getAs(mimetype):Drive.Files.export(lpFile, lpFile.id, doc.getAs(<type>), options);
    对于看似合理的类型,它会失败并出现错误:

    MimeType.GOOGLE_DOCS:很抱歉,出现服务器错误。请稍等,然后重试。
    MimeType.MICROSOFT_WORD:不支持从application/vnd.google-apps.document 转换为application/vnd.openxmlformats-officedocument.wordprocessingml.document

这些错误确实有道理,因为内部 Google Docs MimeType 不可导出(您不能“下载为”此文件类型,因为数据已保留但 Google 希望保留它),Document#getAs(mimeType) 的文档表明文档服务仅支持 PDF 导出。实际上,尝试用 doc.getBlob() 强制 BlobgetAs(mimeType) 失败,并出现错误:

不支持从application/pdf 转换为application/vnd.openxmlformats-officedocument.wordprocessingml.document

  1. 使用DriveApp 获取Blob,而不是文档服务:
    Drive.Files.update(lpFile, lpFile.id, DriveApp.getFileById(smallPrintId).getBlob(), options);
    这与doc.getBlob() 存在相同的问题,并且可能使用相同的内部方法。

  2. 使用DriveApp#getAs会出现与Document#getAs相同的错误


考虑到原生 Apps Script 实现的限制,我随后使用高级服务获取了Blob 数据。这有点棘手,因为返回的File 资源实际上不是文件,而是有关文件的元数据。使用 REST API 获取 Blob 需要将文件导出到所需的 MimeType。从上面我们知道,PDF 格式的Blob 无法正确导入,因为这是上述尝试使用的格式。我们也知道 Google Docs 格式不可导出,所以只剩下 MS Word 的.docx

var blob = getBlobViaURL_(smallPrintId, MimeType.MICROSOFT_WORD);
Drive.Files.update(lpFile, lpFile.id, blob, options);

其中getBlobViaURL_ 为 (still-broken) Drive.Files.export() Apps 脚本方法实现了来自 this SO question 的解决方法。

此方法成功地使用“小字体”文件中的确切内容更新现有的“大字体”文件 - 至少对于我的测试文档而言。鉴于它涉及下载内容,而不是使用导出方法可用的内部现有数据,因此对于较大的文件可能会失败。

测试脚本:

function copyContentFromAtoB() {
  var smallPrintId = "some id";
  var largePrintId = "some other id";

  // You must first enable the Drive "Advanced Service" before this will work.
  // Get the file metadata of the to-be-updated file.
  var lpFile = Drive.Files.get(largePrintId);
  // View available options on the relevant Drive REST API pages.
  var options = {
    updateViewedDate: false,
  };
  // Ideally this would use Drive.Files.export, but there is a bug in the Apps Script
  // client library's implementation: https://issuetracker.google.com/issues/36765129
  var blob = getBlobViaURL_(smallPrintId, MimeType.MICROSOFT_WORD);

  // Replace the contents of the large print version with that of the small print version.
  Drive.Files.update(lpFile, lpFile.id, blob, options);
}
// Below function derived from https://stackoverflow.com/a/42925916/9337071
function getBlobViaURL_(id, mimeType) {
  var url = "https://www.googleapis.com/drive/v2/files/"+id+"/export?mimeType="+ mimeType;
  var resp = UrlFetchApp.fetch(url, {
    headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}
  });
  return resp.getBlob();
}

【讨论】:

  • 努力的“A”!非常感谢 - 我会回来报告的。
猜你喜欢
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
  • 1970-01-01
相关资源
最近更新 更多