2016 年 1 月

第 31 卷,第 1 期

Windows 10 - 在 Windows 10 应用中使用 OneDrive REST API

作者:Laurent Bugnion

在以往框架(如 Windows Phone 8)中,OneDrive 团队提供了一款非常方便好用的 SDK,但开发者的自由度并未因此增加。例如,使用内置按钮控件才可以实现登录机制,但开发者无法更改外观和行为。但是最困难的部分在于,预定义的体验无法使代码在平台之间共享。

但是,根据 HTTP 请求(GET、POST 和 PUT 等),OneDrive 团队现在提供了一种新型 REST API。此方法可灵活地与大型云文件存储进行交互,使用众所周知的代码共享技术构建跨平台代码以在所有 Windows 平台(甚至具有 Xamarin 平台的 iOS 和 Android)上运行。

本文分为两部分,第一部分介绍如何利用新型 OneDrive API 构建通用 Windows 平台 (UWP) 应用。首先,您将了解 REST API 的工作原理以及开发者将如何与其进行交互。您将看到用户如何使用 oAuth 登录系统以及如何利用文件系统操作(如浏览文件夹、获取文件信息、获取文件内容、上载文件,等等)。此外,您还将了解如何执行其他操作,如访问应用文件夹和与朋友共享某项的链接。

在下一篇文章中,我们将讨论 OneDrive 团队的新可移植类库 (PCL),并将此处所述操作封装在可添加到 UWP 应用的便捷库中,但也可以封装在其他支持的框架(如 ASP.NET、Xamarin.iOS、Xamarin.Android 或 Xamarin.Forms)中。

注意: 除了可用于 Xamarin.Android 和 Xamarin.iOS 平台的 PCL 外,OneDrive 团队还为两个平台提供了本机 SDK。

示例代码

您可以从 galasoft.ch/s/msdnonedrive 下载示例代码。它会演示简单的 UWP 应用如何使用低级 REST API 在 OneDrive 服务上执行操作。为了证明代码可轻松移植,还为 Xamarin.Android 实施了相同的应用,并将相同的原则用于其他平台。

了解 REST API

REST API 将使用 HTTP 作为传输协议,并依赖于此协议的方法(GET、POST、PUT 和 DELETE 等)和标准错误代码(200 成功、400 错误请求和 500 服务器错误等)。通过唯一 URI(也可具有参数)可访问每个 API 入口点。在某些情况下,可以使用简单的 GET 方法和查询字符串将信息发送给服务并获得结果,但也可以通过将某些串行化的对象发送到 JSON 来构建更复杂的请求。

REST API 越来越被广泛使用,开发者应对此感到欣慰,因为它提供了一种易于理解的方式与 Web 服务进行通信。最重要的是,它可以在 C# 中构建可移植的组件,且可以在所有受支持的平台上使用这些组件。另一个显著优势是,HTTP 是基于文本的,请求可以轻松地穿过防火墙和代理。

但是,与低级 HTTP 方法通信看起来很多工作非常繁重,尤其对于不习惯在异步编程中使用最新开发的开发者。使用回叫构建异步客户端对于开发者来说并非最佳方法,因为可能会出现深层嵌套和线程问题。令人欣慰的是,两种相对较新的开发已大大缓解了 C# 程序员的负担:HttpClient 组件和 async/await 关键字。例如,访问 OneDrive 音乐文件夹如同构建 URI 和发送 GET 请求一样简便。

var uri = new Uri(
  "https://api.onedrive.com/v1.0/drive/special/music");
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", AccessToken);
var json = await client.GetStringAsync(uri);

生成的 JSON 代码可以进行反序列化(如,使用 JSON.NET 库)以获取应用程序中使用的 .NET 对象。此代码(绝对无需登录或错误处理)显示如何将复杂的操作变得简单流畅。此外,此代码将在 HttpClient 支持的任何平台(包括 Windows Presentation Foundation (WPF)、ASP.NET、Windows 10 和 Xamarin 等等)上良好运行。

注册应用

可以调用 OneDrive API 之前,必须在 OneDrive 开发中心注册您的应用,并对其进行配置和获取客户端 ID 密钥。注册机制如 bit.ly/1GPBaWL 中所述。

注册新应用时,请确保转到“API 设置”页面,并将“移动或桌面客户端应用”设置设为“是”。 所有其他设置可保留默认设置。然后,从“API 设置”页面检索客户端 ID,并将其保存以便稍后使用。

必须了解不同的术语和需要各 ID 的原因:

  • 客户端 ID: 这是 UWP 应用的唯一 ID。您可以将具有相同客户端 ID 的多个客户端应用程序连接到 Microsoft 服务,但通常建议一个应用程序使用一个客户端 ID。客户端 ID 链接到 UWP 应用的信息(如名称和图标等)。创建应用时会生成客户端 ID,且永不变更。
  • 客户端密钥: 这是创建 UWP 应用时生成的唯一标识符。但是,在应用生存期内此代码可能会变更。例如,如果客户端密钥受到了黑客攻击,则可以生成一个新的,更新应用后将拒绝黑客应用进行访问。请注意,客户端密钥通常仅用于服务器应用。
  • 用户 ID 和密码: 用户登录时,需要输入用户名和密码。借助 OAuth,登录交互只发生在用户和 OneDrive 之间,无需客户端应用的知识。实际上,使用 WebView(登录对话显示其中)可实现此目的。
  • 访问令牌: 用户成功登录后,身份验证服务会返回访问令牌。此令牌有效期仅为 60 分钟,到期后用户必须重新登录。每次请求均必须发送令牌,以证明用户通过了身份验证。此身份验证模式在文档中称为“令牌流”。
  • 刷新令牌: 应用可以请求并保存此令牌,以在过期时刷新访问令牌。如果长期在后台模式下使用应用且需要在没有用户交互的情况下定期刷新数据,这会很有用。此身份验证模式称为“代码流”,如 bit.ly/1MQ3KOb 所述。在本文中,我们将只使用更易于实施的“令牌流”。

尝试试用令牌

如果要在未首先实施身份验证的情况下快速尝试新 REST 请求,OneDrive 开发中心可以使您获得试用令牌(有效期为一小时),通过执行以下步骤可以使用此令牌:

  • 转到 bit.ly/1MQ3KOb
  • 找到“立即试用”部分,然后单击“获得令牌”按钮。
  • 如果需要,请登录并确认您授权开发中心访问您的 OneDrive 帐户。
  • 登录成功后,Web 主窗口中将显示试用令牌。
  • 创建名为 TrialOneDrive 的新 UWP 应用。
  • 打开 MainPage.xaml 并添加名为 TrialButton 的按钮。
  • 打开 MainPage.xaml.cs 并为 TrialButton Click 事件添加事件处理程序,如图 1 所示。请注意,此事件处理程序必须使用“async”关键字,因为所有 OneDrive 操作均异步。
  • 图 1 的代码中,将字符串 YOUR TRIAL TOKEN 替换为您从开发中心网站复制的试用令牌。请勿复制单词“Authorization: bearer”!
  • 将断点放在事件处理程序的最后一行,以便检查 JSON 变量。
  • 运行应用程序并单击按钮。
  • 在监视窗口中检查已检索的 JSON 代码。您应该可以看到有关音乐文件夹的信息,如文件夹名称、创建日期、最后修改日期、子级计数、文件夹 ID(可稍后用于各种文件系统操作)、登录用户名等。

图 1 为 TrialButton Click 事件添加事件处理程序

TrialButton.Click += async (s, e) =>
{
  var uri = new Uri(
    "https://api.onedrive.com/v1.0/drive/special/music");
  var client = new HttpClient();
  client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", "YOUR TRIAL TOKEN");
  var json = await client.GetStringAsync(uri);
};

请记住,试用令牌一小时后会过期,因此如果您要向老板演示此应用程序,请记得获取新的试用令牌!

使用 OAuth 进行身份验证

现在您已注册应用程序并了解重要术语,您可以实施身份验证。此处为所要执行的步骤,如图 2 所示:

  1. 用户可启动身份验证,例如通过单击按钮。
  2. 应用程序检查访问令牌是否可用。
  3. 如果可用,则应用已通过身份验证且用户可以移到下一操作。如果没有可用的访问令牌,应用程序会导航到包含 WebView 的 XAML 页面。
  4. XAML 页面设置 WebView 的初始 URL 以加载身份验证终点的页面。XAML 页面还会订阅 WebView 的 WebNavigationCompleted 事件,以便监控此控件中的流量。本文稍后将介绍如何结构化初始 URL。
  5. WebView 从身份验证终结点加载 HTML。
  6. 用户将其用户名和密码输入“HTML 身份验证”页面。请注意,此交互严格限制在用户和 OneDrive 服务器之间。XAML 页面仅起到容器的作用。
  7. 用户按下“HTML”按钮可将此表单提交给身份验证服务器。如果用户已设置它,将显示其他页面以处理双重身份验证。
  8. 如果凭据正确,身份验证服务器会将 WebView 重定向到特殊的 URL 以指示登录成功。此 URL 也将访问令牌作为其中一个查询字符串参数。XAML 页面检测发生的重定向,并可以从 WebView 的新 URL 分析访问令牌。
  9. “身份验证”页面会从重定向的 URI 分析访问令牌。
  10. 应用程序导航回原始 XAML 页面。保存访问令牌以便用于将来请求。

OAuth 工作流
图 2 OAuth 工作流

注意: 了解 OAuth 的工作原理非常重要,Windows 10 开发者幸好具有较简便的备用 WebAuthenticationBroker。在本文中,我会使用“低级”OAuth 机制并将讨论 WebAuthenticationBroker。

了解范围

用户登录时,应用程序需要通知 OneDrive 服务它将需要的功能范围。通过在身份验证 URL 中指定范围可以实现此目的。服务当前支持以下范围:

  • 单一登录:wl.signin。
  • 脱机访问:wl.offline_access。这可使应用程序获得“刷新令牌”。使用“令牌流”身份验证时,会忽略此范围。
  • readonly 访问:onedrive.readonly。这可以使您的应用程序获得对文件和文件夹的只读访问权限。如果应用程序尝试修改文件或上载新文件,服务会返回错误代码“403 Forbidden”。
  • readwrite 访问:onedrive.readwrite。这可以使您的应用程序获得对文件和文件夹的读写访问权限。
  • AppFolder:onedrive.appfolder。这可使应用程序访问所谓的“应用文件夹”。稍后我将在本文中更详细地讨论此特殊的文件夹。请注意,请求 readwrite 范围时,将自动授予此范围。但是,显式请求 appfolder 将导致图 3 所示的对话中提及此范围,这是一个更好的 UX。

图 3 启动身份验证

if (!_service.CheckAuthenticate(
  async () =>
  {
    var dialog = new MessageDialog("You are authenticated!", "Success!");
    await dialog.ShowAsync();
    Frame.GoBack();
  },
  async () =>
  {
    var dialog = new MessageDialog("Problem when authenticating!", "Sorry!");
    await dialog.ShowAsync();
    Frame.GoBack();
  }))
{
  Frame.Navigate(typeof (AuthenticationPage));
};

用户在身份验证网页中输入凭据后,将显示一个对话,要求他确认应用程序请求的权限,如图 4 所示。用户可以随时改变主意并可以撤销部分权限。若要执行此操作,用户需登录到 OneDrive 网站上的相应帐户,导航到“安全和隐私”并选择“应用和服务”下方的“管理权限”链接。在本示例中,我们将始终请求单一登录、readwrite 和 appfolder 访问。

身份验证确认
图 4 身份验证确认

创建初始 URL

用于启动身份验证进程的 URL 需要携带有关应用程序本身、所请求的功能(范围)、身份验证模式和重定向 URI 的信息。

身份验证模式可以是“令牌”或“代码”。在本文和此示例中,我使用了“令牌”模式,即每次重新启动应用程序或每过一小时,用户需要确认登录。这听起来很烦人,但实际上用户仅需在身份验证对话中按“是”按钮即可确认登录,如图 4 所示。

重定向 URI 是登录成功时 OneDrive 服务将应用程序重定向到的地址。对于 Web 应用程序,在“API 设置”选项卡中,它是您应用程序中页面的 URI 并配置在 OneDrive 开发中心。但如果是 UWP 应用,您应将此字段保留为空。反之,我们将依赖于预定义的重定向 URI:

htt://login.live.com/oauth20_desktop.srf

总结

现在您已了解身份验证基于 OAuth 的工作原理,让我们看一些代码。通过单击“身份验证”按钮,您可以在简单的示例中使用此过程。

您使用在 PCL 中实施、称为“OneDriveService”的类。OneDriveService 在 App.xaml.cs 中实例化,且您可以将“客户端 ID”传送给它。

首先,如果您的 MainPage 已通过身份验证(即,已存在访问令牌),则会请求 OneDrive 服务。您将两个委托传递给 CheckAuthenticate 方法调用:身份验证成功时将调用的操作,以及出错时将调用的操作。

如果服务尚未通过身份验证,MainPage 会使用其“框架”属性导航到 AuthenticationPage,如图 5 所示。此页是一个简单的 XAML 页面并具有可获取整个屏幕的 WebView,用户将在此处输入用户名和密码并进行确认。

图 5 AuthenticationPage 的代码

public sealed partial class AuthenticationPage
{
  private readonly OneDriveService _service;
  public AuthenticationPage()
  {
    InitializeComponent();
    _service = ((App)Application.Current).ServiceInstance;
    Loaded += (s, e) =>
    {
      var uri = _service.GetStartUri();
      Web.Navigate(uri);
    };
    Web.NavigationCompleted += (s, e) =>
    {
      if (_service.CheckRedirectUrl(e.Uri.AbsoluteUri))
      {
        _service.ContinueGetTokens(e.Uri);
      }
    };
    Web.NavigationFailed += (s, e) =>
    {
      _service.ContinueGetTokens(null);
    };
  }
}

加载页面时,您从 OneDriveService 获取身份验证 URI:

https://login.live.com/oauth20_authorize.srf?client_id=000000004C169646&
scope=wl.signin+onedrive.readwrite+onedrive.appfolder&response_type=token&
redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf

如上所述,此 URI 包含所有必要信息,如客户端 ID、客户端密码、范围和重定向 URL 等。

请注意,返回访问令牌前,将重定向 WebView 数次。这就是为什么您始终在 WebView 的 NavigationCompleted 事件中检查重定向 URI。最终检测到 oauth20_desktop.srf URI 时,OneDriveService 将从查询字符串参数检索访问令牌。其他信息(到期日期、令牌类型、范围、用户 ID 等)会传递到查询字符串,但在此处可将其忽略。具有访问令牌的重定向 URL 在此处进行了简化:

https://login.live.com/oauth20_desktop.srf?lc=1033#access_token=EwB4Aq1D...1iiZA%3d&
token_type=bearer&expires_in=3600&scope=wl.signin%20onedrive.readwrite%20onedrive.appfolder
%20onedrive.readonly&user_id=8e5323e8b7c7a0928d03e10811531234

用户通过身份验证后,应用程序可以开始与文件和文件夹进行交互。在本文中,我将集中讨论一些操作,但是一旦理解原理,将可以非常轻松扩展应用程序以包含其他服务。

根文件夹

首先,我将讨论根文件夹。此文件夹在 OneDrive 中是唯一的,且是各其他项的父项。

根据 OneDrive 文档,使用以下请求可获取根文件夹: 获取 /drive/root。此请求将返回 JSON 响应,如 bit.ly/1M5w4NV 所述。JSON 响应可以反序列化,且它包含的信息可用于将来其他请求。

文件和文件夹结构 现在,必须了解文件系统是如何构建的。OneDrive 依靠 Facet 系统来提供有关文件和文件夹的信息。例如,文件也可以是图像或照片,并提供有关文件(如图像的宽/高和照片的照相机型号)的其他信息。以下列表显示了当前可用的 Facet 和一些最重要的属性:

  • 项(名称、ID、下载 URL、父引用等)
  • 文件夹(子级计数)
  • 文件
  • 音频(相册、艺术家、比特率、持续时间、标题等)
  • 图像(宽、高)
  • 照片(相机品牌和型号、拍照日期)
  • 视频(持续时间、比特率、宽、高)

将新文件上载到 OneDrive 时,将自动对其进行分析并将添加一些元数据。例如,Word 文件只是一个文件。但用照相机拍摄的图片不仅是文件,还是照片和图像。所有这些 Facet 均包含有关文件的其他信息,如此列表所示。

对从 OneDrive 服务获取的 JSON 进行分析时,您可以将这些类型映射到 C# 类。如果某项是文件夹、文件、图像和视频等,通过检查 JSON 可以非常轻松地找到。例如,图 6 显示了根文件夹的 JSON 响应提取。您可以看到文件夹属性包含有关文件夹子级计数的信息。如果要获取有关照片的信息,您将看到图像和照片属性分别充满有关宽度和高度、相机品牌和型号的信息。

在本文提供的示例应用程序中,您在响应文件夹所包含的类中反序列化 JSON,这将映射到 Facet 系统。

现在您已理解响应的工作原理,我们可以使用此处所示的代码轻松地访问根文件夹信息。

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", AccessToken);
var uri = new Uri("https://api.onedrive.com/v1.0/drive/root");
var json = await client.GetStringAsync(uri);
var rootFolder = JsonConvert.DeserializeObject<ItemInfoResponse>(json);

要查看所使用的代码,您可以先执行简单示例并按“身份验证”按钮,然后按“获得根文件夹”按钮。

获得文件夹的子项图 6 所示,响应仅包含有关文件夹的元信息。您知道文件夹具有多少子项,但您需要执行多个请求以获得子项列表。此处,OneDrive 文档还可提供帮助并指明您需要对 /drive/items/{item-id}/children 请求 GET,如图 7 所示。

图 6 根文件夹的 JSON 响应

{
  "createdBy": {
    "user": {
      "displayName": "Laurent Bugnion",
      "id": "fb0d8f9700498123"
    }
  },
  "createdDateTime": "2010-11-27T17:09:25.513Z",
  "id": "FB0D8F97004979CD!ABC",
  "lastModifiedBy": {
    "user": {
      "displayName": "Laurent Bugnion",
      "id": " fb0d8f9700498123"
    }
  },
  "lastModifiedDateTime": "2015-10-04T14:36:36.217Z",
  "name": "root",
  "size": 178558187077,
  "webUrl": "https://onedrive.live.com/?cid=fb0d8f9700498123",
  "folder": {
    "childCount": 18
  }
}

图 7 获得子项列表

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", AccessToken);
var request = string.Format("/drive/items/{0}/children", info.Id);
var uri = new Uri(
  "https://api.onedrive.com/v1.0"
  + request);
var json = await client.GetStringAsync(uri);
var response = JsonConvert.DeserializeObject<ParseChildrenResponse>(json);
return response.Value;

图 7 中,将 JSON 反序列化到名为 Parse­ChildrenResponse 的类。这将再次映射到 JSON 响应,可将子项列表包装到名为“value”的 JavaScript 阵列。ParseChildrenResponse 类如图 8 所示。

图 8 ParseChildrenResponse 类

public class ParseChildrenResponse
{
  public IList<ItemInfoResponse> Value
  {
    get;
    set;
  }
  [JsonProperty("@odata.nextLink")]
  public string NextLink
  {
    get;
    set;
  }
}

因为每个子项均为 ItemInfoResponse,您知道如何处理这些子项并决定各子项是否为文件夹、文件、照片和音频文件等。

请注意,如果您想要避免执行两个调用以检索文件夹信息和填充其子项列表,也可以使用以下请求,这可以在一个调用中执行所有操作:

 

GET /drive/items/root?expand=children

了解分页 访问具有许多子项的文件夹时,OneDrive 服务发送的响应可能不完整并需要分页。默认情况下,此服务仅返回最多包含 200 个子项的列表。如果您浏览的文件夹具有更多子项,则将名为“@odata.nextLink”的属性添加到子项列表,如图 8 所示。此属性包含应用程序进入下一“页面”需执行的下一请求的 URI。 在 UWP 应用中,可以选择立即调用服务以获得下一页的项(这将正常运行,因为长列表会被虚拟化),也可以显示“更多”按钮并在应用中实施页面导航。

浏览子文件夹 具有文件夹 ID 后,您便可以使用以下请求轻松地浏览此文件夹:

GET /drive/items/{item-id}

在您已具有文件夹 ID 时这会很不错,但有时您没有此信息。通过另一个语法,您可以改用相对于根的路径来检索文件夹的信息。您可以在图 9 中看到此语法。

图 9 通过路径浏览子文件夹

var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", AccessToken);
var request = string.Format("/drive/root:/{0}", path);
var uri = new Uri(
  "https://api.onedrive.com/v1.0"
  + request);
var json = await client.GetStringAsync(uri);
var result = JsonConvert.DeserializeObject<ItemInfoResponse>(json);
return result;

应用文件夹

OneDrive 有一些特殊的文件夹,如音乐、文档和照片等。最近引入了一个新的特殊文件夹: 应用文件夹。这是一个适用于应用程序的特殊文件夹,可保存漫游设置、上载备份等。请注意,“应用文件夹”在任何方面均不具有安全性或隐藏性。实际上,它保留在名为“Apps”的文件夹中,位于用户的 OneDrive 根中。应用的“应用文件夹”与 OneDrive 应用程序使用相同的名称,即为获得客户端 ID 而进行注册时输入的名称。请注意,根据 OneDrive 应用程序的设置,应用程序的名称可能已使用不同的语言进行本地化。用户通过 OneDrive 网站或任何应用程序对“应用文件夹”具有完全访问权限,甚至可以删除文件夹(如果选择)。

引入“应用文件夹”概念之前,应用程序将其设置和其他文件保存在 OneDrive 根或自定义文件夹中(现在许多应用程序仍是如此)。使用这些项的“应用文件夹”非常简洁且 UX 更出色。根据 OneDrive 文档 (bit.ly/1MBUkS2),获得“应用文件夹”信息的请求是:

GET /drive/special/approot

如您所见,可以轻松地在任何应用程序中实施“应用文件夹”!

下载文件

如果无法上载或下载文件,将可以使用 OneDrive 做什么? 在本部分及下一部分中,您将看到如何执行此重要操作,非常简单。

为了下载文件的内容,OneDrive 创建了一个可在项响应中另存为属性的 DownloadUrl。但是请注意,URL 仅在短时间内有效,因此如果缓存文件信息,您可能需要先从服务再次获取信息,如图 10 所示。

图 10 下载文件内容

public async Task<Stream> RefreshAndDownloadContent(
  ItemInfoResponse model,
  bool refreshFirst)
{
  var client = new HttpClient();
  client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", AccessToken);
  // Refresh the item's information
  if (refreshFirst)
  {
    var request = string.Format("/drive/items/{0}", model.Id);
    var uri = new Uri(
      "https://api.onedrive.com/v1.0"
      + request );
    var json = await client.GetStringAsync(uri);
    var refreshedItem =
      JsonConvert.DeserializeObject<ItemInfoResponse>(json);
    model.DownloadUrl = refreshedItem.DownloadUrl;
  }
  var response = await client.GetAsync(model.DownloadUrl);
  var stream = await response.Content.ReadAsStreamAsync();
  return stream;
}

一旦获得文件内容流,便可以在本地对其进行处理和保存等。此简单示例使用 FileSavePicker 要求用户提供可保存文件的位置。

上载文件

同样,一旦获得文件流,上载文件也将非常简便。在 Windows 10 中,使用 StorageFile 实例可以实现此目的,如使用 FileOpenPicker。读取流后,便可以将它上载到 OneDrive。根据文档,您需要使用 PUT 操作:

PUT /drive/items/{parent-id}:/{filename}:/content

HttpClient 通过 HttpContent 实例支持 PUT 方法。在这种情况下,因为您具有原始文件流,所以可以使用 StreamContent 实例。如果您只想要保存文本文件,则可以使用 StringContent 等。

需要传递到服务的其他信息是将保存文件的文件夹 ID。在图 11 所示的简单示例中,parentId 被传递到上载方法。请注意,PUT 操作会返回 JSON 内容,此内容描述了 OneDrive 上文件的新信息,如 ID、Web URL、下载 URL 等。

图 11 上载文件内容

var content = new StreamContent(stream);
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", AccessToken);
var uri = new Uri(
  "https://api.onedrive.com/v1.0"
  + string.Format(
    "/drive/items/{0}:/{1}:/content",
    parentId,
    fileName));
var response = await client.PutAsync(uri, content);
var json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<ItemInfoResponse>(json);
return result;

除了此处所述的简单上载外,OneDrive API 也通过不同的语法提供了一系列可恢复的上载。此简单上载适用于小于 100MB 的文件。如果文件较大,您应查看 bit.ly/1PB31Cn 中的文档。

获得唯一链接

我将在此处演示的最后一个操作是,如何为某项获得唯一“共享”链接。此操作可以非常方便地通过电子邮件、SMS 和社交媒体等将唯一链接发送给朋友。图 12 显示如何根据项 ID 获得此信息。在此示例中,您可以获得指向上一演示中所上载文件的链接。

图 12 获得共享链接

public async Task<LinkResponseInfo> GetLink(
  LinkKind kind,
  string fileId)
{
  // LinkKind id View or Edit
  var client = new HttpClient();
  client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", AccessToken);
  var request = string.Format("/drive/items/{0}/action.createLink", fileId);
  var uri = new Uri(
    "https://api.onedrive.com/v1.0"
    + request);
  var requestJson = JsonConvert.SerializeObject(
    new RequestLinkInfo
    {
      Type = kind.ToString().ToLower()
    });
  var content = new StringContent(
    requestJson,
    Encoding.UTF8,
    "application/json");
  var response = await client.PostAsync(uri, content);
  var result = JsonConvert.DeserializeObject<LinkResponseInfo>(
    await response.Content.ReadAsStringAsync());
  return result;
}

根据文档,此请求与先前执行的 GET 请求略有不同,因为服务需要更多的详细信息。“共享链接”请求如下: POST /drive/items/{item-id}/action.createLink。您需要传递到服务的信息是 JSON 代码段,其中链接类型为:“view”或“edit”,如:{ "type": "view" }

总结

有一些其他操作本文中未作介绍,如删除文件、上载文件内容和同步更改。但是,通常操作均遵循相同的模式,并可以使用 HttpClient、HTTP 方法和 JSON 来执行。这都得益于 Microsoft .NET Framework 中异步编程的诸多先进功能,此类操作可流畅轻松地在任何受支持的框架中实施,包括 Windows 10、WPF、Windows Phone、Xamarin.iOS、Xamarin.Android 等。鉴于使用如此方便,确实没有理由不在 UWP 应用中使用这些类型的云交互,如备份内容或漫游设置。在下一篇文章中,我们将介绍如何借助 OneDrive 团队最新发布的 PCL 来帮助您进一步简化集成。


Laurent Bugnion是 IdentityMine(Microsoft 技术的领先公司之一和金牌合作伙伴)的高级总监,他居住在瑞士苏黎世。他在 2010 年编写的书《Silverlight 4 Unleashed》由 Sams 出版,该书是《Silverlight 2 Unleashed》(2008) 的高级续集。他为多个刊物写作,第二年成为 Microsoft 区域总监,第九年成为 Microsoft MVP。他撰写了非常著名的适用于 Windows、WPF、Xamarin 的开源框架 MVVM Light,并撰写了广受好评的有关 MVVM Light 的 Pluralsight 参考课程。您可通过其博客 galasoft.ch 与他联系。

衷心感谢以下技术专家对本文的审阅: Corrado Cavalli (Gaia) 和 Ryan Gregg (Microsoft)