【问题标题】:Google Drive API: Create Folder: Allow conflict error if folder by name existsGoogle Drive API:创建文件夹:如果存在按名称的文件夹,则允许冲突错误
【发布时间】:2020-03-29 18:33:57
【问题描述】:

讨论

Google Drive API v3Create Folder

云驱动 API 比较

创建文件夹时的其他云盘API,包括Box APIDropbox API,如果同名文件夹已经存在,都会返回冲突错误父文件夹。

但是,Google Drive API 默认允许创建同名文件夹。

问题

如果尝试在 Google Drive 父文件夹中创建同名文件夹,有没有办法返回冲突错误?

如果我采用 API 的方法首先按名称搜索文件夹,然后创建文件夹(如果不存在),那么这可能会导致并行进程在按名称创建唯一文件夹时执行相同任务而导致可能的竞争条件。

示例

Google Drive API 在curl 中创建文件夹调用

curl "https://www.googleapis.com/drive/v3/files" \
--request POST \
--verbose \
--write-out 'HTTPSTATUS:%{http_code}' \
--silent \
--header "authorization: Bearer [** ACCESS TOKEN **]" \
--header "cache-control: no-cache" \
--header "content-type: application/json; charset=utf-8" \
--header "Accept: application/json" \
--data '{ \
    "mimeType":"application\/vnd.google-apps.folder", \
    "name": "[** FOLDER NAME **]", \
    "parents": ["root"] \
}'

每次调用都会在 Google Drive 父文件夹中创建一个具有唯一文件夹 ID,但文件夹名称相同的新文件夹。我希望避免这种情况:

Success [HTTP status: 200]
{
  "kind": "drive#file",
  "id": "1mpy2-TVeZDTL8vZ6fKHTyoGoFHX-18EN",
  "name": "TEST",
  "mimeType": "application/vnd.google-apps.folder"
}
...
Success [HTTP status: 200]
{
  "kind": "drive#file",
  "id": "1iqYnEWOVFcWO3jWX1IgIv2wxtGVYruQX",
  "name": "TEST",
  "mimeType": "application/vnd.google-apps.folder"
}

感谢您在获得单一调用方法以返回冲突错误自动重命名方面的任何帮助。

【问题讨论】:

  • 杰夫,你能找到一个单一的呼叫解决方案吗?如果我们有办法将字符串散列为有效的 Google 项目 ID,那么两个工作人员将能够在创建请求期间使用相同的 ID 并获得碰撞检测。但如果 Google 自己记账它生成的 ID,那么这样的哈希函数似乎不太可能......

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


【解决方案1】:
  • 如果在特定文件夹中创建新文件夹时存在相同的文件夹名称,您希望返回冲突错误。
  • 您希望将此与异步进程一起使用。
    • 在这种情况下,您不想创建重复的文件夹名称。
  • 您希望通过 Drive API 的一次 API 调用来实现此目的。

如果我的理解是正确的,那么这个答案呢?请认为这只是几个可能的答案之一。

问题和解决方法:

在 Google 云端硬盘中,所有文件和文件夹均由唯一 ID 管理。这样,可以在一个文件夹中创建同名的文件和文件夹。使用 Drive API 时,使用的 ID 不是文件名和文件夹名。因此,为了使用 Drive API 实现您的目标,需要搜索文件夹名称。而且,为了防止创建与异步处理相同的文件夹名称,需要进行排他处理。遗憾的是,仅使用简单的 curl 命令无法实现您的目标。

从上述情况来看,为了只使用简单的 curl 命令来实现您的目标,我想使用 Web 应用程序作为 API 作为一种解决方法。 Web Apps 由 Google Apps Script 创建,可以像 API 一样使用。至此,我认为您的目标可以通过此解决方法实现。

用法:

要使用此解决方法,请执行以下流程。

  1. 创建新的 Google Apps 脚本项目。

    1. 访问script.google.com。 在这种情况下,将显示登录屏幕。所以请登录谷歌。这样,脚本编辑器就打开了。
    2. 当您第一次访问 script.google.com 时,您将被重定向到一个介绍 Apps 脚本的页面。届时,请点击Start Scripting进入脚本编辑器。
    3. 在左上角输入GAS项目的文件名。
  2. 复制并粘贴以下示例脚本。用作服务器端的脚本。

    function doGet(e) {
      var lock = LockService.getScriptLock();
      if (lock.tryLock(10000)) {
        var parent, folder;
        if (e.parameter.parentId) {
          parent = DriveApp.getFolderById(e.parameter.parentId);
          folder = parent.getFoldersByName(e.parameter.folderName);
        } else {
          parent = DriveApp.getRootFolder();
          folder = DriveApp.getFoldersByName(e.parameter.folderName);
        }
        if (folder.hasNext()) {
          lock.releaseLock();
          var err = {error: "Same folder name is existing."};
          return ContentService.createTextOutput(JSON.stringify(err)).setMimeType(ContentService.MimeType.JSON);
        }
        var folderId = parent.createFolder(e.parameter.folderName).getId();
        lock.releaseLock();
        var msg = {message: "Done.", folderId: folderId};
        return ContentService.createTextOutput(JSON.stringify(msg)).setMimeType(ContentService.MimeType.JSON);
      }
    }
    
    • 很遗憾,Web 应用程序无法管理响应代码。在这种情况下,即使脚本发生错误,也会返回状态码 200。所以我将响应值作为 JSON 对象返回。
    • 在此脚本中,进程以独占处理方式运行。这样,即使您使用异步进程运行请求,也不会创建相同的文件夹名称。
  3. 部署网络应用程序。

    1. 在脚本编辑器上,通过“发布”->“部署为 Web 应用”打开一个对话框。
    2. “执行应用程序为:”选择“我”
    3. “谁有权访问应用程序:”选择“仅限我自己”
      • 在这种情况下,为了访问 Web 应用程序,需要使用访问令牌。
      • 如果使用“任何人,甚至匿名”而不是“仅我自己”,则不需要使用访问令牌。
    4. 单击“部署”按钮作为新的“项目版本”。
    5. 自动打开“需要授权”对话框。
      1. 点击“查看权限”。
      2. 选择自己的帐户。
      3. 点击“此应用未验证”中的“高级”。
      4. 点击“转到###项目名称###(不安全)”
      5. 点击“允许”按钮。
    6. 点击“确定”。
    7. 复制 Web 应用程序的 URL。就像https://script.google.com/macros/s/###/exec
      • 当您修改 Google Apps 脚本时,请重新部署为新版本。这样,修改后的脚本就会反映到 Web 应用程序中。请注意这一点。
      • 我认为也可以使用开发者模式,因为使用了访问令牌。但是在您的情况下,我认为服务器端的脚本可能适合作为版本进行管理。所以我不建议使用开发者模式。
  4. 通过以下 curl 命令使用 deoloyed Web 应用程序。

    curl -L \
      -H "Authorization: Bearer ###" \
      "https://script.google.com/macros/s/###/exec?parentId=###&folderName=###"
    
    • parentIdfolderName 用作查询参数。
    • parentId的文件夹中存在folderName的同名文件夹时,返回{"error":"Same folder name is existing."}
    • parentId的文件夹中不存在与folderName相同的文件夹名称时,将创建新文件夹并返回{"message":"Done.","folderId":"### folder ID of created folder ###"}

参考资料:

如果我误解了您的问题并且这不是您想要的方向,我深表歉意。

【讨论】:

  • 感谢您的回复,很好的解决方案,您确实理解了问题。 curl 中提供的示例仅演示本机 Drive v3 API 调用。我正在使用 Google Drive API 创建一个集成解决方案,使用通过 Google OAuth 2.0 对客户端驱动器的同意授权访问,文件/文件夹读/写的范围有限。查看您的 Web App + Google Apps 脚本需要在 Google 环境中进行代码维护,这是我无法轻易移交给其他编码员的解决方案。更简单的切换将是在 Google 环境之外使用锁定解决方案的代码解决方案。谢谢。
  • @Jeff Tanner 感谢您的回复。如果我的回答对您的情况有用。我很高兴。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-02
相关资源
最近更新 更多