Как легко работать с OneDrive из приложений UWP


    Продолжаю рассказывать об интересных/полезных вещах из мира 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

      0
      Немного не по теме, но видел ваш ответ на SO про BackgoundDownloader. Скажите, откуда он берет значения куки, когда им пользуешься? И можно ли как-то эти куки выпилить?
        0
        Вы сейчас про тот случай, когда WinINet не поддерживается и нужна аутентификация с помощью HttpClient? Про это здесь написано. Но тут записываются значения в реестр, а не считываются.
        Лучше на SO и прокомментируйте) — там гораздо больше шансов что подскажут
          0
          А что такое Microsoft Graph? Офис 365 подписка нужна или можно и для outllok аккаунтов использовать?
            0
            Это возможность из одного API получить доступ и к Office 365 и к Outlook и к AD и к OneDrive. Пока что не особо разбирался, но исходя из примера Microsoft Graph Connect Sample for UWP, для некоторых вещей обычного аккаунта должно быть достаточно.
              0
              Судя по документации это все-таки для 365 http://graph.microsoft.io/en-us/docs
                0
                Попробовал пример. Работает и с обычным outlook аккаунтом. Только приложение нужно создать новое, т.к. старые не поддерживают v2.0 endpoint
            0
            >Рассматривая контент, вы можете заметить, что в строке Uri путь к файлу обрамлен двоеточием.
            А почему так?
              0
              Один из вариантов синтаксиса разделителя path.
              Это потому что знак двоеточия не может содержаться в имени файла, а значит может использоваться как какой-то спец формат.
              0
              Тоесть LiveSDK https://www.nuget.org/packages/LiveSDK/ уже всё? Нужно переходить на OneDrive SDK?
                0
                Да, нужно переходить или на OneDrive SDK или на Microsoft Graph. Как долго еще будет поддерживаться Live SDK мне неизвестно.

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое