【UWP】China Daily中数据同步到One Drive的实现

博主开发的UWP应用China Daily中,支持将生词本、收藏夹等数据同步到OneDrive,现在我们来看看这个功能具体是如何实现的。

1. 在项目中安装OneDriveSDK

image
特别注意:请安装Microsoft.OneDriveSDK的1.x.x版本!(2.x.x版本和1.x.x版本差异比较大,前者不兼容后者。博主在这篇博客中以1.2.0版本的OneDriveSDK进行讲解,如果你确实希望使用最新版本SDK,本篇博客可能对你的参考价值极其有限)
额外说明:你也可以通过包管理控制台安装OneDriveSDK。安装语法为:PM> Install-Package Microsoft.OneDriveSDK -Version 1.2.0

2. 将当前项目与应用商店关联起来

image

image

3. SDK的使用

Microsoft.OneDriveSDK使用OAuth 2.0进行用户授权管理,一旦用户授予相关权限后,我们就可以进行相关操作了(我的China Daily向用户申请了三个OneDrive操作权限:登录、读写、离线使用权)。详细的权限管理信息请参见微软相关文档,而下方的图片则展示了文档中的关键信息供你参考
image

3.1 调用登录接口获取授权
// 全局的Client
private static IOneDriveClient _client;

// 所请求的权限
private static string[] scopes = new string[] { "onedrive.readwrite", "wl.offline_access", "wl.signin" };  
/// <summary>
/// 身份验证
/// </summary>
/// <returns></returns>
public static async Task<bool> LogInAsync()  
{
    try
    {
        _client = OneDriveClientExtensions.GetUniversalClient(scopes);
        var session = await _client.AuthenticateAsync();

        return session != null;
    }
    catch (OneDriveException ex)
    {
        Debug.WriteLine(ex.Message);

        return false;
    }
}

说明:我创建了一个OneDriveUtil的静态类,并在类里面实现身份验证、上传、下载的方法。所以下述(方法调用部分除外)的字段、方法都使用了static关键字进行限制。(值得一提的是:OneDriveSDK十分的人性化,因为我们不需要主动管理Session,一个全局的Client就足够了)

3.2 上传文件到OneDrive
/// <summary>
/// 上传文件到OneDrive
/// </summary>
/// <returns></returns>
public static async Task<bool> UploadFileAsync()  
{
    var file = await StorageFile.GetFileFromPathAsync($"ms-appx:///Assets/Images/{fileName}");

    return await UploadFileAsync(file, OneDriveFilePath);
}

/// <summary>
/// 上传文件到OneDrive
/// </summary>
/// <param name="file"></param>
/// <param name="path"></param>
/// <returns></returns>
private static async Task<bool> UploadFileAsync(StorageFile file, string serverPath)  
{
    if (file != null)
    {
        var stream = await file.OpenStreamForReadAsync();

        var item = await _client
                            .Drive
                            .Root
                            .ItemWithPath(serverPath)
                            .Content
                            .Request()
                            .PutAsync<Item>(stream);

        return true;
    }

    return false;
}
3.3 从OneDrive下载文件
/// <summary>
/// 从OneDrive下载文件
/// </summary>
/// <returns></returns>
public static async Task<Stream> DownloadFileAsync()  
{
    return await DownloadFileAsync(OneDriveFilePath);
}

/// <summary>
/// 从OneDrive下载文件
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
private static async Task<Stream> DownloadFileAsync(string serverPath)  
{
    var item = await _client
                        .Drive
                        .Root
                        .ItemWithPath(serverPath)
                        .Request()
                        .GetAsync();

    var stream = await _client
                          .Drive
                          .Items[item.Id]
                          .Content
                          .Request()
                          .GetAsync();

    return stream;
}
3.4 综合调用
// 数据备份功能的实现
if (await OneDriveUtil.LogInAsync())  
{
    var succeed = await OneDriveUtil.UploadFileAsync();
}
// 同步功能的实现
if (await OneDriveUtil.LogInAsync())  
{
    using (var stream = await OneDriveUtil.DownloadFileAsync())
    {
        await ImportDataAsync(stream);
    }
}

/// <summary>
/// 通过文件流导入数据
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public static async Task ImportDataAsync(Stream stream)  
{
    if (stream != null)
    {
        try
        {
            // 这个地方使用了图片库,一定要记得申请相关权限(见下图)
            var lib = KnownFolders.PicturesLibrary;
            var file = await lib.CreateFileAsync(OneDriveUtil.fileName, CreationCollisionOption.ReplaceExisting);

            byte[] buffer = new byte[stream.Length];
            await stream.ReadAsync(buffer, 0, buffer.Length);

            var fs = await file.OpenStreamForWriteAsync();
            fs.Write(buffer, 0, buffer.Length);

            // TODO: Notify task succeed
        }
        catch
        {
            // TODO: Notify task failed
        }
    }
    else
    {
        // TODO: Notify task failed
    }
}

image

3.5 初次运行

初次运行,系统会弹框告知用户应用正在申请授权(如下图)。若成功授权,则以后一般不会再弹出提示,除非身份验证过期。 image

4. Demo

Download Demo

5. 参考

Win10开发:OneDrive SDK 的使用 http://blog.csdn.net/zmq570235977/article/details/50520247