2014-11-04 23 views
2

我有一个可以自动保存更改的谷歌驱动器应用程序。如果你有两个活动会话,那么他们会覆盖对方。该应用程序支持合并更改,但我无法看到如何安全地将其与驱动器API集成。有些选项我已考虑:如何使用Google Drive API同步冲突的更改

  1. 版安全承诺

    • 使用谷歌驱动器“仅更新,如果在驱动电流修订== X否则失败”
    • 如果失败则获取最新版本,合并并重试

    • 问题:我不认为驱动器支持这一点。以前的API版本使用了etags,但在当前的文档中我没有看到这一点。

  2. 提交前的检查

    • 检查当前保存的版本,如果仍然电流,节省
    • 否则下载,合并和更新

    • 问题:明显的竞争条件客户之间

  3. 提交后检查

    • 保存新版本
    • 如果如预期的新版本:完成
    • 如果新版本高于预期:下载以前的版本,合并和更新

    • 问题:我没有太多的信心,这是安全的。我可以看到多个客户端进入编辑循环。

  4. 谷歌的实时API - 场结合

    • 与谷歌RT数据模型替换文件格式

    • 问题:这需要只是谷歌-RT

      重新设计
  5. 谷歌的实时API - 文档支持

    • 使用谷歌API的RT外部文档支持

    • 问题:我不认为这解决了问题

我真的很想获得#1的方法,但任何建议都会有所帮助。我很满意客户端之间的基本锁定/切换方案,但我认为Drive也不支持这种方案。

+0

什么是你改变文件,即MIME类型。它是一种本地谷歌类型,如文档或电子表格,还是它自己的文件类型,如HTML或专有? – pinoyyid 2014-11-04 09:28:34

+0

它是一种专有格式 - 目前用json编码,但可能变成二进制。 – daw 2014-11-05 07:08:30

回答

1

根据here,使用etags的“If-Match”仍然有效。不确定它是否适用于数据,但至少它适用于元数据。

+0

不幸的是,不再使用API​​的v3。 – 2018-02-28 22:30:11

0

要在user1828559的回答跟进,下面的Java代码似乎运作良好:

private File updateDriveFile(Drive drive, File file, byte[] data) throws IOException { 
    try { 
     ByteArrayContent mediaContent = new ByteArrayContent(MIME_TYPE, data); 
     Drive.Files.Update update = drive.files().update(file.getId(), file, mediaContent); 

     update.getRequestHeaders().setIfMatch(file.getEtag()); 

     return update.execute(); 
    } 
    catch (GoogleJsonResponseException e) { 
     if (isConflictError(e.getDetails())) { 
      logger.warn("ETag precondition failed, concurrent modification detected!"); 
      return null; 
     } 

     throw e; 
    } 
} 

private boolean isConflictError(GoogleJsonError error) { 
    if (error.getCode() == 412) { 
     final List<GoogleJsonError.ErrorInfo> errors = error.getErrors(); 
     if (errors != null && errors.size() == 1) { 
      final GoogleJsonError.ErrorInfo errorInfo = errors.get(0); 
      if ("header".equals(errorInfo.getLocationType()) && 
        "If-Match".equals(errorInfo.getLocation()) && 
        "conditionNotMet".equals(errorInfo.getReason())) 
       return true; 
     } 
    } 

    return false; 
}