42

这是我正在尝试做的事情:给定一个 Google 文档 URL,我想获取文档 ID 以在 Google Drive 上创建一个副本。我知道我可以通过一些正则表达式或在 URL 上替换来实现这一点,但是由于有几种不同的形式可以在 URL 中表示同一个文档,所以我想找到一个通用的解决方案。

目前,这是我能想到的最好的:

function getFileIdFromUrl(url) {
  try {
    return getDocIdFromUrl(url);
  } catch (e) {
    return getSpreadsheetIdFromUrl(url);
  }
}

function getDocIdFromUrl(url) {
  var doc = null;
  try {
    doc = DocumentApp.openByUrl(url);
  } catch (e) {
    doc = DocumentApp.openByUrl(url + "/edit");
  }
  return doc.getId();
}

function getSpreadsheetIdFromUrl(url) {
  var spreadsheet = null;
  try {
    spreadsheet = SpreadsheetApp.openByUrl(url);
  } catch (e) {
    spreadsheet = SpreadsheetApp.openByUrl(url + "/edit");
  }
  return spreadsheet.getId();
}

function copy(url) { // may throw an exception if the URL is invalid or private
   var id = getFileIdFromUrl(url);
   var file = DriveApp.getFileById(id);
   file.makeCopy().setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
}

问题是我的解决方案只涵盖文档和电子表格,我想对任何上传的文件做同样的事情,例如:

https://docs.google.com/file/d/0B-FYu_D7D7x4REdtRVEzVH0eU0/edit

简而言之,我想要这样的东西:

DriveApp.getFileByUrl(url).makeCopy();

有谁知道这是否可能?

任何从文件 URL 中提取文件 ID 的安全解决方案都适合我。

谢谢

4

11 回答 11

108

DriveApp 确实缺少一个getFileByUrl(以及与此相关的文件夹)。您可能希望在Apps Script issue tracker上打开增强请求。

但是我在我的脚本上所做的(因为这些openByUrl函数有些新)是使用正则表达式获取 id。像这样。

function getIdFromUrl(url) { return url.match(/[-\w]{25,}/); }

这个正则表达式适用于我尝试过的任何 google url:文件夹和文件的 Drive url、Fusion Tables、Spreadsheets、Docs、Presentation 等。它只是在“看起来像”Google 密钥的字符串中查找任何内容。也就是说,任何足够大的字符串,其中只有(谷歌键)有效字符。

此外,即使它直接接收 ID 而不是 URL,它也可以工作。当您向用户询问链接时,这很有用,因为有些人可能会直接粘贴 id 而不是 url 并且它仍然有效。

- 编辑

还有一些其他答案和评论解决了我自己从未遇到但可能发生的一些边缘情况,例如尝试在嵌套文件夹 URL 上获取文件夹 ID,或者当您的 G-Suite 域长度超过 25 个字符时。对于这些情况,您可能需要使用更严格的正则表达式。

通过快速浏览下面的建议,我推荐以下建议,/[-\w]{25,}(?!.*[-\w]{25,})/因为它仍然非常简单并且应该解决这些情况。

于 2013-05-30T15:50:25.600 回答
6

几乎所有 GoogleDrive/Docs 链接的 url 都是这样的,并且文件 id 出现在这种模式“/d/XXXXXXXX/”中:
https ://drive.google.com/file/d/0B3tB9BU9FRnpcTJmS2FoaktsQzA/view

使用下面的函数,我们可以得到'/d/fileid/',然后从开头截断'/d/',从结尾截断'/'。

public static string getIdFromUrl(string url)
{
    Regex r = new Regex(@"\/d\/(.+)\/", RegexOptions.IgnoreCase);
    Match m = r.Match(url);
    return m.ToString().TrimStart('/', 'd').Trim('/');
}
于 2015-07-03T07:33:42.257 回答
6

我没有足够的声誉来评论接受的答案,但是当驱动器 URL 包含域名并且域名超过 25 个字符时,来自 Henrique G. Abreu 的接受答案失败(只是发现这一点很难:)

否则它非常可靠,我认为是这里提供的最优雅和最强大的。

因此,扩展已接受的答案,以下正则表达式将获得至少 25 个字符长的单词字符或连字符字符串的最后一次出现,其前面紧跟一个不是非单词字符或连字符的字符, 并且可选地后跟相同类型的字符,以及最后可能出现的任何其他垃圾:

/.*[^-\w]([-\w]{25,})[^-\w]?.*/

这失去了接受答案的特征,即它仅在传递 ID 时才会起作用,但这不是我需要的用例。它适用于我测试过的文档和文件夹的所有不同类型的 Drive、Docs、Sheets URL。

于 2018-11-19T03:52:59.850 回答
3

还有一些上面没有提到的 URL 扩展可以包含 ID。

https://drive.google.com/drive/folders/https://drive.google.com/open?id=https://drive.google.com/a/domain.edu.vn/folderview?身份证=

我想我会添加基于这个想法的解决方案,并涵盖上述两个扩展,以及使用 /d/ 的扩展

function getIdFrom(url) {
  var id = "";
  var parts = url.split(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/);
  if (url.indexOf('?id=') >= 0){
     id = (parts[6].split("=")[1]).replace("&usp","");
     return id;
   } else {
   id = parts[5].split("/");
   //Using sort to get the id as it is the longest element. 
   var sortArr = id.sort(function(a,b){return b.length - a.length});
   id = sortArr[0];
   return id;
   }
 }
于 2016-10-29T23:22:45.823 回答
2

我只是想根据两个给定的答案添加我创建的函数,因为两者都不是我想要的。

function templateIdFrom(url) {
  var parts = url.match(/\/d\/(.+)\//);
  if (parts == null || parts.length < 2) {
    return url;
  } else {
    return parts[1];
  }
}

这将获取在/d/next之后的部分/,这就是文档 URL 始终包含其 ID 的方式。如果没有找到匹配项,那么我们只需返回原始参数,假定为 ID。

于 2016-06-13T20:45:53.007 回答
1

openByUrlGoogle Apps 脚本中现在提供了一种方法。

请参阅此处的参考文档查看表格此处查看文档此处查看幻灯片此处查看表单

因为你写道:

我想获取文档 ID 以在 Google Drive 上创建副本

...我假设您本身不需要 ID 。通过 URL 获取 sheet/doc/slide/form 后,您可以对其进行复制。

于 2019-08-17T05:54:03.077 回答
1

对于 Python:

对于固定长度的谷歌驱动器 ID,您可以使用:

regex = "([\w-]){33}|([\w-]){19}"
match = re.search(regex,url)

Google 驱动器使用 33 个字符用于普通驱动器,19 个字符用于团队驱动器

另一种不使用固定长度而是使用前面模式的方法:

regex = "(?<=/folders/)([\w-]+)|(?<=%2Ffolders%2F)([\w-]+)|(?<=/file/d/)([\w-]+)|(?<=%2Ffile%2Fd%2F)([\w-]+)|(?<=id=)([\w-]+)|(?<=id%3D)([\w-]+)"

match = re.search(regex,url)
于 2020-08-21T21:04:18.420 回答
1

Henrique 建议的解决方案可能无法涵盖 Google 云端硬盘文件由 Google Workspace 用户共享且域可能是文件 URL 的一部分的情况。如果域名很长,则会捕获域名而不是文件 URL。

https://drive.google.com/a/thisisaverylongdomainname.org/file/d/1djf7XfuKx4Px55x7ahvMa5uznp3Ibe5vd7Y/view?usp=sharing

Google Drive 生成​​的文件 ID 不包含句点 (.),因此这个修改过的 RegEx 可以防止捕获域名。

function getFileIdFromDriveUrl(url) {
  var match = url.match(/([a-z0-9_-]{25,})[$/&?]/i);
  return match ? match[1] : null;
}
于 2020-12-22T13:04:53.127 回答
0

要从 url 电子表格中提取 id,我使用下面的代码。它适用于 Google 电子表格和云端硬盘中的 Excel。也许也适用于其他文档。

function getIdSheetFromUrl_(url)
{
    var id = url.split('id=')[1];
    if(!id)
    {
        id = url.split('/d/')[1];
        id = id.split('/edit')[0]; // here we have the id
    }
    return DriveApp.getFileById(id);
}
于 2020-09-10T19:29:50.603 回答
0

如果您在电子表格的单元格中有指向 Google Drive 文件的 URL,我相信您可以使用以下公式提取 fileID:

=mid({cellAddress},33,33)

例子:

=中(A2,33,33)

于 2020-11-21T03:17:53.530 回答
0

我有一张工作表,我在其中将 URL 放入单元格中,并将其拉入 App 脚本以执行其他操作(例如在包含工作表内容的文件夹内创建文档)。

我只是用简单str.split("/")的方法把 ID 拉出来。有时,如果 URL 包含/u/0/,我只是将索引向下移动一点:

if (sheet.getRange("D2").getValue().split("/")[4] === "u") {
  folderId = sheet.getRange("D2").getValue().split("/")[7];
} else {
  folderId = sheet.getRange("D2").getValue().split("/")[5];
}

尽管它仅适用于两种给定的 Google Drive URL 格式。我没有遇到很多其他人,但是drive.google.com/drive/folders/#folderIddrive.google.com/drive/u/o/folders/#folderId

于 2021-08-13T03:31:07.473 回答