大规模发现文件和检测更改的最佳做法

SharePoint 和 OneDrive 存储数百万个文件。 尝试大规模了解所有文件和更改时,使用正确的调用模式至关重要。 过去,有许多 API 可以访问原子级别的文件。 其中许多 API 大规模效率不高,但适用于单个用户交互。 本指南介绍如何监视 Office 365 租户或 OneDrive,以便应用程序与 Office 365 集成,从而获得最高性能和效率。 通常需要这种类型的应用程序包括同步引擎、备份提供程序、搜索索引器、分类引擎和数据丢失防护提供程序。

获取适当的权限

若要与用户建立信任,请务必使用应用正常运行所需的正确的最小 权限范围 集。 大多数扫描应用程序都希望以应用程序权限进行操作,这表明应用程序是独立于任何特定用户运行的。 若要访问文件,应请求 Files.Read.AllFiles.ReadWrite.All 范围。 若要访问 SharePoint 资源 (包括所有网站集的列表),采用 Sites.Read.AllSites.ReadWrite.All合适。 为了正确处理权限,还需要请求 Sites.FullControl.All

授权类型、权限范围和用户

在 Microsoft Azure 中配置应用程序的权限时,可以在应用程序权限和委派权限之间进行选择。 如上所述,大多数扫描应用程序需要 应用程序权限。 委派权限要求应用程序在已登录用户的上下文中运行,而不是全局操作。 在委派模型中,仅能访问当前用户有权访问的内容。

需要注意的权限的一个重要方面是,当管理员向请求应用程序权限的应用程序授予权限 (而不是) 委托的权限时,权限授予与租户和应用程序关联,而不是与管理员用户相关联。 尽管需要管理员来授予访问权限,但访问权限授予不会授予应用程序任何特殊的管理权限,除了访问应用程序请求的资源范围之外。

对于处理来自 SharePoint 和 OneDrive 的大量数据的应用程序,应遵循一致的调用模式,如下所示。

  1. 发现 –配置要扫描的位置。
  2. Crawl –发现并处理感兴趣的整个文件集。
  3. 通知 –通过通知监视对这些文件的更改。
  4. 处理更改 –仅使用增量查询重新处理已更改的文件。

该模式将如下图所示。 本文详细介绍了实现的每个步骤。

正在扫描 Microsoft Graph 和客户端应用程序之间的调用流

这些元素中的每一个可能具有多种机制,可在 Microsoft Graph API 和现有 SharePoint API 中完成这些机制。 本文的目标是为你提供今天完成每个任务的最佳方式。

发现要扫描的位置

目前,配置希望应用程序扫描的位置是一个手动过程。 在许多情况下,将需要为此步骤提供面向用户的应用程序体验; 如何公开此功能,以及它是否向所有用户公开,还是仅向管理员公开,都由你决定。 将要确定要扫描哪些用户的 OneDrives 以及哪些 SharePoint 站点集合和子站点。

每个用户的 OneDrive 包含一个 驱动器 可以监视。 SharePoint 网站集和子网站可能有多个驱动器,站点中的每个文档库都有一个。 可以通过使用 /drives 端点来发现站点中的每个驱动器。 例如,若要获取租户根站点中的所有驱动器,可以使用:

https://graph.microsoft.com/v1.0/sites/root/drives

驱动器是大规模文件活动的起点。 将使用这些驱动器来获得完整的文件列表,连接 webhooks 以获得通知,并使用增量查询来获得驱动器中项目的变化集。

如何查找 SharePoint 网站集和 OneDrive for Business 驱动器

使用具有应用程序权限的 Microsoft Graph,则可以获得站点集合的完整列表,包括包含 OneDrive for Business 驱动器的站点。 若要获取此列表,请使用以下 API 调用:

GET /sites

站点枚举 API 还支持 增量查询 以获取有关新网站创建或更改站点结构的信息。 当前,对站点枚举的增量查询支持将推出到 Microsoft Graph Beta 版本。 有关增量查询的详细信息,请继续阅读。

若要接收有关新网站集的通知,则可以使用 Microsoft Graph 订阅 终结点订阅 Web 挂钩。 这些通知的目标资源 /sites。 创建或删除新网站集以及创建子网站或列表时,将收到通知。

通过使用增量查询进行爬网和处理

若要获取驱动器中文件的初始列表,请进行单个不带参数的 增量查询 调用。 增量查询为应用提供对所有内容的初始爬网,然后从某个时间点进行后续更改。 增量查询返回每次调用它时获取未来更改所需的链接。

例如,如果要获取 SharePoint 网站中默认文档库中的所有文件,可以使用此查询:

/sites/{siteId}/drive/root/delta

此 API 返回表示驱动器中所有文件的结果页。 使用返回的 检索文件的所有页后,可以使用返回@odata.nextLink@odata.deltaLink的 再次进行增量查询,以获取自上次调用增量查询以来的更改。 请始终记住保留返回 @odata.deltaLink 的 URL,以便稍后可以有效地检查更改。

增量查询返回的链接如下所示:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(driveItem)",
    "@odata.deltaLink": "https://graph.microsoft.com/v1.0/me/drive/root/delta?$select=*%2csharepointIds&token=MzslMjM0OyUyMzE7MzsyM2YwNDVhMS1lNmRmLTQ1N2MtOGQ5NS1hNmViZDVmZWRhNWQ7NjM2NzExNzY2MzIxMDcwMDAwOzE5ODAzMzU5ODslMjM7JTIzOyUyMzQ",
    "value": [
        {
            "@odata.type": "#microsoft.graph.driveItem",
            "createdDateTime": "2017-07-27T02:41:36Z",
…
}

有关更详细的示例,请参阅增量查询 文档

增量查询返回 driveItems 的数组。 如果事先知道需要特定信息,可以在选择语句中加入增量查询的内容。 如果需要的话,还可以在增量调用之后,请求一个特定的 driveItem。 增量查询仍将有助于缩小所要查询的更改项目数量,使应用更有效率。

使用 Webhook 获取更改通知

若要充分利用驱动器上发生变化的增量查询,则需要一个有效的策略来了解何时返回并请求更改。 过去,可能已编写应用,在某个固定的时间间隔轮询 OneDrive 和 SharePoint,并自行枚举更改。 使用增量查询时,枚举部分已完成,因此只需知道何时返回。 Webhook 允许避免轮询服务,而是在感兴趣的内容发生更改时收到通知。 反复轮询服务或以高速率轮询会导致应用程序因过多的呼叫模式而受到限制。

Webhook 是通过使用用于 Microsoft Graph 的订阅 API 附加的。 可以在 Microsoft Graph 站点上找到有关 Microsoft Graph webhook 和 Subscriptions API 的完整文档

需要创建与特定资源关联的订阅 (在本例中为驱动器)。 驱动器支持 Webhook 的“更新”更改类型。 “更新”指示驱动器中的内容已更改或已添加或删除新内容。 Webhook 订阅具有需要定期刷新的关联超时。 请参阅前面提到的有关如何刷新订阅的文档。 建议在订阅 Webhook 后立即使用增量查询与上次更改令牌结合使用,以确保不会错过在初始爬网和设置 Webhook 之间发生的任何更改。

即使 Webhook 发送应用程序通知,也可能需要定期提供增量查询,以确保在收到通知后长时间内,不会错过任何更改。 对于此定期检查,我们建议每天不超过一次。 增量查询仍使你能够轻松跟进,并且不会错过系统中的任何更改。

接收安全事件的 Webhook 通知

OneDrive 和 SharePoint 支持向发送应用程序安全事件通知。 若要订阅这些事件,则需要在请求中添加“prefer:includesecuritywebhooks”标题,以注册 webhook。 注册 Webhook 后,当项的权限更改时,将收到通知。 此标题适用于 SharePoint 和 OneDrive for Business 帐户,但不适用于 OneDrive 消费者版本的帐户。

处理更改

在应用程序通过 webhook 收到通知后,需要通过立即向 Microsoft Graph 发送 202 - 接受代码来确认通知。 应在开始任何耗时处理之前发送此代码。 未能执行此操作会导致发送其他重试,应用可能会将其视为假通知。

使用增量查询跟进确认以了解最新更改,并且应用应为最新版本。 如果需要特定驱动器上的大量流量模式,则应考虑在缩短间隔而不是在每次更改通知后调用增量查询。 此外,请确保存储 deltaLink 参数中返回的新值,以获取用于再次调用 API 的新令牌。

如果处理需要下载单个文件的内容,则可以使用 cTag 属性来确定自上次下载文件以来文件的内容是否已更改。 知道要下载文件后,可以访问增量查询响应中返回的 DriveItem 的 /content 属性。

扫描权限层次结构

默认情况下,增量查询响应将包括项目的共享信息,即使它们从其父级继承其权限,本身没有直接的共享更改。 请注意,增量查询响应仅包括对其内容或元数据具有直接更改的项,以及已更改项的父层次结构。 这通常会导致执行后续调用,以便获取每个项目(而不仅仅是共享信息发生了更改的项目)的权限详细信息。 通过向增量查询请求添加“首选: 分层共享”标题,能够帮助更好地了解权限更改的发生方式。

如果提供了“首选: 分层共享”标题,将返回以下对象的共享信息: 权限层次结构的根以及明确具有共享更改的项目。 如果共享更改是从某个项目中删除共享,你会发现一个空的共享 facet,用以区分从其父级继承的项目和唯一但没有共享链接的项目。 你还将在未共享用于建立初始作用域的权限层次结构的根处看到这个空的共享 facet。

在许多扫描场景中,可能会对权限的更改特别感兴趣。 若要在增量查询响应中明确哪些更改是由权限更改造成的,可提供“首选: deltashowsharingchanges”标题。 当提供此标题时,由于权限更改而出现在增量查询响应中的所有项目,在针对 Microsoft Graph 进行调用时,将有 "@microsoft.graph.sharedChanged":"True" OData注释存在,当直接使用 SharePoint 或 OneDrive API 时,注释将是 "@oneDrive.sharedChanged":"True"。 与安全 Webhook 一样,此功能适用于 SharePoint 和 OneDrive for Business 帐户,但不适用于 OneDrive 消费者版本的帐户。

受到限制时会发生什么?

在某些情况下,应用程序可能会从 Microsoft Graph 获得 429 或 503 响应。 这表示请求当前受到限制。 需要记住的一点是,SharePoint 会根据每个客户租户的应用程序使用情况对应用程序进行节流。 为租户中的一个资源提供请求会相应地为你提供更少的资源来调用同一租户的另一个资源。 最终,应用收到限制响应的原因可能有多种,在这些情况下,应用正确响应至关重要。

若要从接收 429 或 503 响应代码中恢复,请在等待响应标头的“Retry-After”字段中指定的持续时间后重试。 如果限制持续存在,Retry-After 值可能会随着时间推移而变长,从而使系统能够恢复。 由于滥用的调用模式,在回调之前不遵循重试的应用将受到阻止。

等待 429 或 503 恢复时,应确保暂停对服务发出的所有进一步请求。 这在多线程方案中尤为重要。 在收到限制响应的同时拨打其他电话会延长应用限制的时间。

有关 Microsoft Graph 资源如何使用限制的更多详细信息,请参阅 Microsoft Graph 限制指南