从 Google Apps 脚本上的 URL 获取文件 ID 的最简单方法
Posted
技术标签:
【中文标题】从 Google Apps 脚本上的 URL 获取文件 ID 的最简单方法【英文标题】:Easiest way to get file ID from URL on Google Apps Script 【发布时间】:2013-05-26 06:10:02 【问题描述】:这是我想要做的:给定一个 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 的安全解决方案都适合我。
谢谢
【问题讨论】:
【参考方案1】: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,但它仍然有效。
--编辑
还有一些其他答案和 cmets 解决了一些我自己从未遇到过但可能会发生的边缘情况,例如尝试在嵌套文件夹 URL 上获取文件夹 ID,或者当您拥有 25 岁以上的 G-Suite 域时长字符。对于这些情况,您可能需要使用更严格的正则表达式。
通过快速浏览下面的建议,我推荐以下/[-\w]25,(?!.*[-\w]25,)/
,因为它仍然非常简单,应该可以解决这些情况。
【讨论】:
我做了一些测试,看起来很棒!谢谢你。只是一个问题:这个数字 (25) 真的是 google docs id 的最小长度吗? 这在任何地方都没有记录。我只是从各种文件中获取了一堆 URL,查看最短的一个并给予折扣以防万一:) 还检查了 url 的另一部分是否远程接近 25 个直字符(中间没有点,等),所以它不会与其他部分混淆。 使用the regex suggested by aquadeep 不太可能进行不需要的匹配。然后使用 (group) 仅提取正则表达式的 ID 部分: url.match(/\/d\/(.25,)\//)[1]; @Kenigmatic,不需要的匹配似乎不太可能,我更愿意相信 25 个字符作为基本长度,而不是 ID 总是以数字开头。我还认为我们可以相信 ID 将始终由数字、字母和连字符组成。为什么要使用点? 刚刚发现您的编辑在最后一段中添加了一个不需要的“$”——不确定它应该在那里?猜猜我复制了哪一个并与之斗争:)。【参考方案2】:我有一张表格,我在其中将 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/#folderId
和drive.google.com/drive/u/o/folders/#folderId
,我还没有遇到很多其他人。
【讨论】:
【参考方案3】:Henrique 建议的解决方案可能无法涵盖 Google 云端硬盘文件由 Google Workspace 用户共享且域可能是文件网址的一部分的情况。如果域名很长,则会捕获域名而不是文件 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;
【讨论】:
【参考方案4】:如果您在电子表格的单元格中有指向 Google Drive 文件的 URL,我相信您可以使用以下公式提取 fileID:
=mid(cellAddress,33,33)
例子:
=mid(A2,33,33)
【讨论】:
【参考方案5】:要从 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);
【讨论】:
【参考方案6】:对于 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)
【讨论】:
【参考方案7】:现在可以在 Google Apps 脚本中使用 openByUrl
方法。
请参阅参考文档here for Sheets、here for Docs、here for Slides 和 here for Forms。
因为你写了:
我想获取文档 ID 以在 Google 云端硬盘上创建副本
...我假设您不需要 ID 本身。通过 URL 获取 sheet/doc/slide/form 后,可以进行复制。
【讨论】:
【参考方案8】:我没有足够的声誉来评论接受的答案,但是当驱动器 URL 包含域名并且域名超过 25 个字符时,来自 Henrique G. Abreu 的接受的答案失败(只是很难找到这一点:)
否则它非常可靠,我认为是此处提供的最优雅和最强大的。
因此,扩展已接受的答案,以下正则表达式将获得至少 25 个字符长的单词字符或连字符字符串的最后一次出现,其前面紧跟一个不是非单词字符的字符或连字符,并且可选地后跟相同类型的字符,以及末尾可能出现的任何其他垃圾:
/.*[^-\w]([-\w]25,)[^-\w]?.*/
这失去了接受答案的特征,即仅在传递 ID 时它会起作用,但这不是我需要的用例。它适用于我测试过的文档和文件夹的所有不同类型的云端硬盘、文档、表格 URL。
【讨论】:
【参考方案9】:还有一些上面没有提到的可以包含 ID 的 URL 扩展。
https://drive.google.com/drive/folders/ 和 https://drive.google.com/open?id= 和 https://drive.google.com/a/domain.edu.vn/folderview?id=
我想我会添加基于 this idea 的解决方案,涵盖上述两个扩展以及使用 /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;
【讨论】:
【参考方案10】:我只是想根据两个给定的答案添加我创建的函数,因为两者都不是我想要的。
function templateIdFrom(url)
var parts = url.match(/\/d\/(.+)\//);
if (parts == null || parts.length < 2)
return url;
else
return parts[1];
这将获取/d/
之后的部分,直到下一个/
,这就是文档 URL 始终包含其 ID 的方式。如果没有找到匹配项,那么我们只需返回原始参数,假定为 ID。
【讨论】:
【参考方案11】:几乎所有 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('/');
【讨论】:
以上是关于从 Google Apps 脚本上的 URL 获取文件 ID 的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章
无法通过 Google Apps 脚本中的 YouTube 数据 API 从云端硬盘上传:空响应
无法通过 Google Apps 脚本中的 YouTube 数据 API 从云端硬盘上传:空响应
如何通过使用数组从 Google 表格中提取数据并格式化来优化 Apps 脚本代码?
如何从 Google 电子表格中的 Google Apps 脚本自动更新“站点地图”功能?