Продолжаю рассказывать об интересных/полезных вещах из мира XAML/C# приложений UWP. OneDrive API является частью Microsoft Graph. Для работы с OneDrive можно использовать OneDrive REST API, которое использует протокол HTTP и в частности его методы GET, POST, DELETE, PUT…

Кроме того, в соответствии с новыми принципами работы Microsoft, была создана библиотека обертка OneDrive SDK for CSharp, которая облегчает работу и использование сервиса из кода ваших приложений.

OneDrive SDK for CSharp — это Portable Class Library (PCL) которая предназначена для следующих типов проектов:

.NET 4.5.1
.NET for Windows Store apps
Windows Phone 8.1 and higher

Для того чтобы установить SDK можно выполнить команду в консоли диспетчера пакетов NuGet

Install-Package Microsoft.OneDriveSDK

или в VS менеджере NuGet воспользоваться поиском по фразе Microsoft.OneDriveSDK

После создания универсального приложения необходимо его связать с магазином Windows. Таким образом оно автоматически будет зарегистрировано в группе приложений Live SDK. По адресу https://apps.dev.microsoft.com/#/appList можно проверить, что приложение зарегистрировано в группе Live SDK applications. Насколько я понял, все приложения Windows Store по умолчанию попадают в эту группу.

Аутентификация происходит с помощью нескольких строчек кода:

    string[] scopes = { "wl.signin", "onedrive.readwrite" };
    IOneDriveClient _client = OneDriveClientExtensions.GetClientUsingOnlineIdAuthenticator(scopes);
    await _client.AuthenticateAsync();

Все права/разрешения (scopes) доступны по ссылке: Authentication scopes

При аутентификации открывается новое окно, в котором пользователь сможет ввести свои данные:



Выйти можно с помощью следующего кода:

await _client.SignOutAsync();

Приведу самые типичные операции с файлами. Скачать файл можно с помощью вот такого сниппета:

    string[] scopes = { "wl.signin", "onedrive.readwrite" };
    IOneDriveClient _client = OneDriveClientExtensions.GetClientUsingOnlineIdAuthenticator(scopes);
    AccountSession session = await _client.AuthenticateAsync();

    if (!_client.IsAuthenticated) return;

    Item item = await _client
             .Drive
             .Root
             .ItemWithPath("CodeExamples/MyDemo.zip")
             .Request()
             .GetAsync();

    using (Stream contentStream = await _client
                       .Drive
                       .Items[item.Id]
                       .Content
                       .Request()
                       .GetAsync())
    {
        StorageFile file = await ApplicationData.Current.LocalFolder.
                                            CreateFileAsync("MyDemo.zip", CreationCollisionOption.OpenIfExists);

        using (Stream outputstream = await file.OpenStreamForWriteAsync())
        {
            await contentStream.CopyToAsync(outputstream);
        }
    }

А загрузить с помощью такого:


    string[] scopes = { "wl.signin", "onedrive.readwrite" };
    IOneDriveClient _client = OneDriveClientExtensions.GetClientUsingOnlineIdAuthenticator(scopes);
    AccountSession acse = await _client.AuthenticateAsync();

    if (!_client.IsAuthenticated) return;

    FileOpenPicker fileOpenPicker = new FileOpenPicker();
    fileOpenPicker.FileTypeFilter.Add(".jpg");
    StorageFile file = await fileOpenPicker.PickSingleFileAsync();

    if (file != null)
    {
        using (Stream contentStream = await file.OpenStreamForReadAsync())
        {
            var uploadedItem = await _client
                                         .Drive
                                         .Root
                                         .ItemWithPath("CodeExamples/" + file.Name)
                                         .Content
                                         .Request()
                                         .PutAsync<Item>(contentStream);
        }
    }

Описание других операций с файлами доступно по ссылке на GitHub: Items in the OneDrive SDK for C#

А вот таким образом можно получить список элементов в корневой папке:

    IChildrenCollectionPage ic=  await _client
           .Drive
           .Root
           .Children
           .Request()
           .GetAsync();

Теперь давайте немного рассмотрим эту же операцию, но уже с помощью REST API. Для этого нам понадобится Access Token, который мы можем получить из объекта активной сессии – AccountSession (используем возможности OneDrive SDK для упрощения работы с REST API). И еще понадобится класс HttpClient из пространства System.Net.Http:

    Uri uri = new Uri("https://api.onedrive.com/v1.0/drive/root/children");
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization =
                                            new AuthenticationHeaderValue("Bearer", session.AccessToken);
    string jsonstring = await client.GetStringAsync(uri);

В результате получим строку в виде JSON с перечислением всех находящихся на OneDrive в корневой папке элементов.
Вы можете не регистрировать приложение в Store, а получить временный Access Token (действительный в течение часа) для экспериментов. Для этого необходимо на страничке OneDrive authentication and sign-in нажать кнопку Get Token.

Первый способ очевидно проще и короче, но второй тоже может быть полезен. Скажем, можно получить ссылку на файл вот так:

    Uri uri = new Uri("https://api.onedrive.com/v1.0/drive/root:/CodeExamples/MyDemo.zip:/action.createLink");
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization =
                                            new AuthenticationHeaderValue("Bearer", session.AccessToken);

    var requestJson = JsonConvert.SerializeObject( new RequestLinkInfo { type = "view" });
    var content = new StringContent(requestJson,Encoding.UTF8,"application/json");
    var response = await client.PostAsync(uri,content);

    LinkResponseInfo result = JsonConvert.DeserializeObject<LinkResponseInfo>(
                                                                        await response.Content.ReadAsStringAsync());

Рассматривая контент, вы можете заметить, что в строке Uri путь к файлу обрамлен двоеточием. Альтернативно можно использовать id файла /drive/items/{item-id}/action.createLink.

Для сериализации и десериализации JSON-а нам понадобятся следующие классы:

  public class RequestLinkInfo
    {
        public string type { get; set; }  // возможные значения: view, edit или embed
        public string scope { get; set; } // optional - возможные значения: anonymous или organization
    }

    public class LinkResponseInfo
    {
        public string id { get; set; }
        public string[] roles { get; set; }
        public Link link { get; set; }
    }

    public class Link
    {
        public string type { get; set; }
        public string scope { get; set; }
        public string webUrl { get; set; }
        public OneDriveApplication application { get; set; }
    }

    public class OneDriveApplication
    {
        public string id { get; set; }
        public string displayName { get; set; }
    }

Сам URL можно будет получить из объекта result:

    string fileurl = result.link.webUrl;

Что интересно, так это то, что можно даже использовать старенький Live API и получить доступ к информации о том пользователе, который залогинился:

    Uri uri = new Uri("https://apis.live.net/v5.0/me");
    HttpClient client = new HttpClient();
    client.DefaultRequestHeaders.Authorization =
                                            new AuthenticationHeaderValue("Bearer", session.AccessToken);
    string jsonstring = await client.GetStringAsync(uri); 

Хотя, как долго Live API еще будет доступно сказать сложно.
Официальная документация доступна здесь: Develop with the OneDrive API
Поделиться с друзьями
-->

Комментарии (10)


  1. dmitry_dvm
    08.08.2016 22:17

    Немного не по теме, но видел ваш ответ на SO про BackgoundDownloader. Скажите, откуда он берет значения куки, когда им пользуешься? И можно ли как-то эти куки выпилить?


  1. asommer
    08.08.2016 22:49

    Вы сейчас про тот случай, когда WinINet не поддерживается и нужна аутентификация с помощью HttpClient? Про это здесь написано. Но тут записываются значения в реестр, а не считываются.
    Лучше на SO и прокомментируйте) — там гораздо больше шансов что подскажут


  1. SlotDB
    09.08.2016 11:03

    А что такое Microsoft Graph? Офис 365 подписка нужна или можно и для outllok аккаунтов использовать?


    1. asommer
      09.08.2016 12:06

      Это возможность из одного API получить доступ и к Office 365 и к Outlook и к AD и к OneDrive. Пока что не особо разбирался, но исходя из примера Microsoft Graph Connect Sample for UWP, для некоторых вещей обычного аккаунта должно быть достаточно.


      1. SlotDB
        09.08.2016 16:50

        Судя по документации это все-таки для 365 http://graph.microsoft.io/en-us/docs


        1. asommer
          09.08.2016 18:37

          Попробовал пример. Работает и с обычным outlook аккаунтом. Только приложение нужно создать новое, т.к. старые не поддерживают v2.0 endpoint


  1. dmitry_dvm
    09.08.2016 14:30

    >Рассматривая контент, вы можете заметить, что в строке Uri путь к файлу обрамлен двоеточием.
    А почему так?


    1. asommer
      09.08.2016 15:11

      Один из вариантов синтаксиса разделителя path.
      Это потому что знак двоеточия не может содержаться в имени файла, а значит может использоваться как какой-то спец формат.


  1. Bogdan0x400
    15.08.2016 20:29

    Тоесть LiveSDK https://www.nuget.org/packages/LiveSDK/ уже всё? Нужно переходить на OneDrive SDK?


    1. asommer
      16.08.2016 00:14

      Да, нужно переходить или на OneDrive SDK или на Microsoft Graph. Как долго еще будет поддерживаться Live SDK мне неизвестно.