【问题标题】:How to revert back document to a previous revision如何将文档恢复到以前的版本
【发布时间】:2019-09-11 09:47:54
【问题描述】:

我想将 GAS 中的 Google 文档(或任何其他文档)恢复到较早的版本。我设法访问了修订版,甚至下载了较旧的修订版,但是如何将文档恢复到指定的修订版?

【问题讨论】:

  • 您能否分享一下您如何访问@WillemS 的修订版?

标签: google-apps-script google-drive-api


【解决方案1】:
  • 您想恢复到以前版本的 Google 文档。
  • 您希望使用 Google Apps 脚本实现此目的。

如果我的理解是正确的,那么这个答案呢?

问题和解决方法:

很遗憾,在现阶段,Google Docs 的修订无法直接通过 API 使用脚本进行更改。因此,作为几种解决方法之一,我想建议使用导出的数据覆盖 Google Docs 文件。此变通方法的流程如下。

  1. 从具有修订 ID 的 Google Docs 文件中检索导出的端点。
    • 在这种情况下,Google Docs 文件被导出为 Microsoft Docs 文件。
  2. 从导出的端点检索 blob。
  3. 用检索到的 blob 覆盖 Google 文档。

通过此流程,Google Docs 文件将恢复到以前的版本。

重要提示:

作为重要的一点,当 Google Docs 文件导出为 Microsoft Docs 文件时,在大多数情况下,被覆盖的 Google Docs 文件不会从该版本的原始 Google Docs 更改。但我不确定这种解决方法是否适用于所有情况。所以请注意这一点。

示例脚本:

此解决方法的示例脚本如下。在运行脚本之前,please enable Drive API at Advanced Google services

function myFunction() {
  var revisionId = "1";  // Please set the revision ID you want to revert.
  var googleDocsFileId = "###";  // Please set the Google Docs file ID.

  var endpoints = Drive.Revisions.get(googleDocsFileId, revisionId).exportLinks;
  var keys = Object.keys(endpoints);
  for (var i = 0; i < keys.length; i++) {
    if (keys[i].indexOf("application/vnd.openxmlformats-officedocument") > -1) {
      var endpoint = endpoints[keys[i]] + "&access_token=" + ScriptApp.getOAuthToken();
      var mediaData = UrlFetchApp.fetch(endpoint).getBlob();
      Logger.log(mediaData.getBytes().length)
      Drive.Files.update({}, googleDocsFileId, mediaData);
      break;
    }
  }
}

注意:

  • 即使在 Google Docs 文件恢复到以前的版本后,也可以更改文件的版本。但在您测试上述脚本之前,我建议您使用一个示例 Google 文档文件。
  • 使用此解决方法时,除了 Google Docs 之外的文件也可以恢复到以前的版本。但在这种情况下,请修改脚本。
  • 如果你想完美还原到之前的版本,在当前阶段,我建议手动还原。
  • 例如,当您只想恢复单元格的值时,这可以完美实现。您可以在this thread 看到它作为示例案例。

参考资料:

如果这不是您想要的方向,我深表歉意。

更新日期:2020 年 2 月 7 日

从 2020 年 1 月起,访问令牌不能与 access_token=### 等查询参数一起使用。 Ref 所以请使用请求头的访问令牌而不是查询参数。如下。

var res = UrlFetchApp.fetch(url, {headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}});

【讨论】:

  • 非常感谢。我很荣幸阅读您的开箱即用解决方案。当我想到这一点时:奇怪的是,为了完成我需要的(将文档恢复到以前的版本),我最好不要使用谷歌文档。更简单的解决方法是在 Drive 中使用 Microsoft Word 文档,现在可以轻松查看和编辑(并恢复到以前的版本)。看来这是 Google 不应该忽视的挑战……
  • @WillemS 感谢您的回复。我很高兴你的问题得到了解决。是的。也希望能有直接将Google Docs的修订版移动到原生Google Docs下的方法和API。
  • 太棒了!我确认,该解决方案可以帮助我恢复损坏的谷歌表格
  • @Evgeny 感谢您的评论。我很高兴。
  • @Tanaike:如何将您的更新行添加到原始代码中?
【解决方案2】:

您可以按照these instructions 手动操作。此外,正如您在 revision resource documentation 中看到的那样,您可以更改 published 属性以将特定修订标记为“活动版本”。

要通过 Apps 脚本执行此操作,您需要 enable Google Advanced Services,这将允许您充分使用 API。然后您可以使用update 方法(Documentation here),使用所需修订的ID 并将其published 属性更改为true

请记住,根据文档:

这仅适用于 Google 文档。

【讨论】:

  • 我认为这只会发布修订版,不会将文档恢复到以前的修订版。
  • 感谢您花时间回答我。但是 TheMaster 是对的:您所描述的只会导致 html 版本基于旧版本。它不会更改文档本身。我想以编程方式将文档反转为其原始版本,以便我的用户可以重新编辑它。
  • 确实如此,我为错误道歉。
【解决方案3】:

这是在 中使用google-api-python-client 包实现的一对示例函数。

首先,调用gsGetLatestRevisionId 获取最新版本作为还原点,然后再开始在应用中使用 Google 文档:

from dateutil import parser

def gsGetLatestRevisionId(gc:Resource,gsId:str) -> str:
    '''
    Gets the latest revisionId for a google docs file with id=gsId.
    We can use this as a restore point after manipulating a google spreadsheet 
    :param gc: The authenticated Google drive api discovery.build service
    :param gsId: The google sheets id for the file we want to analyse
    :return: revisionId of the latest revision
    '''
    revisions = gc.revisions().list(fileId=gsId).execute()
    revisionDateIds = {}
    for rd in revisions['revisions']:
        revisionDateIds[parser.parse(rd['modifiedTime'])] = rd['id']
    latestDate = max(revisionDateIds.keys())
    return revisionDateIds[latestDate]

一旦出现严重错误,请致电gsRevertToRevision 将电子表格恢复到之前确定的恢复点:

from io import BytesIO
from googleapiclient.http import MediaIoBaseUpload

def gsRevertToRevision(gc:Resource,gsId:str,revisionId:str) -> dict:
    '''
    Reverts the google docs file with id gsId to the revision identified by 
    revisionId.
    We use this as a restore point pointer so we can revert a google spreadsheet.
    
    :param gc: The authenticated Google drive api discovery.build service
    :param gsId: the google sheets id for the file we want to revert
    :param revisionId: The google sheet's revision id that we want to revert the file to
    :raises [ValueError]: if unable to download the revision file from Google Drive API.
    :return: result of the update to the restored revision 
    '''
    # Get the name of the spreadsheet
    name = ''.join(gc.files().get(fileId=gsId, fields='name').execute().values()) 
    # Get the download links (exportLinks)
    endPoints = gc.revisions().get(fileId=gsId, revisionId=revisionId, 
                                   fields='exportLinks').execute()
    # Different classes of download links are supported, so we choose the one
    # likely to give us the best outcome
    mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    endPoint = endPoints['exportLinks'][mimeType]
    # We use the protected _http functionality in the Google service 
    # object to download this file with the correct headers in place.
    # Hopefully they don't replace or remove the _http method in future 
    # revisions of the google api python library!
    # The result is a tuple with response json information and the actual 
    # file data in the second object. 
    response, fileData = gc._http.request(endPoint)
    if response.status == 200:
        metaData = {
            'name': name, 'mimeType': mimeType,
            }
        fh = BytesIO(fileData)
        mediaBody = MediaIoBaseUpload(fh, mimetype=mimeType,
            chunksize=1024*1024, resumable=True)
        result = gc.files().update(
            fileId=gsId,
            body=metaData,
            media_body=mediaBody
            ).execute()
    else:
        raise ValueError('Unable to download the revision file from google drive api.')     
    return result

这是为与 Google 电子表格一起使用而设计的,但也可以适用于其他文档类型。诀窍是为特定文档选择最实用的exportLink mime-type。我没有概括此功能,因为这更多是概念的演示。此外,转换可能会引入伪影,因此我希望人们不要在没有意识到这个潜在问题的情况下简单地复制和粘贴。

gsRevertToRevision 当然可以单独使用并提供任何有效的revisionId,因此这符合问题中提出的一般用例要求,至少就修订而言。

另一个“特性”是,与其他类似的解决方案不同,它不会创建文件来将下载的实例文件数据写入磁盘。相反,所有内容都保存在 RAM 中。如果您想要以这种方式处理大文件,请记住这一点,因为您最终可能会耗尽内存。

注意!

gsRevertToRevision 通过导出然后重新导入文档实例来工作。这涉及文档类型转换(两次),并可能导致数据和/或功能丢失。确保您的电子表格各个方面都使其重新投入测试。

【讨论】:

    猜你喜欢
    • 2011-02-13
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多