在我的“焕屏”应用中用到了OneDrive同步功能,因此准备写一下OneDrive SDK的简单使用。OneDrive 开发者中心:开发中心
使用SDK需要做一些准备工作
一、在开发者中心注册应用
1、用开发者账号登陆开发者中心,不过这里的开发者中心不是平时常去的dev.windows.com,而是这里 https://account.live.com/developers/applications/index
2、在页面上点击“创建应用程序”,输入应用程序名称并选择语言。然后“我接受”(怎么不是我愿意
3、在API设置页面中将“移动或桌面客户端应用”选择成“是”。如果你要在原有的应用中使用SDK,更改对应应用的API设置即可
二、项目准备
1、新建一个UWP工程,这里命名为OneDriveDemo
2、在工程中安装SDK对应的NuGet包,搜索“Microsoft.OneDriveSDK”
3、将项目工程与应用程序关联
右键项目名,选择“应用商店”->“将应用程序与应用商店关联”
在登陆应用商店之后,在选择应用程序名称页面下面填入新应用名称,或者在应用列表中选择对应应用名
以上,我们完成了SDK使用的准备工作。
要操作OneDrive中的应用,就要让用户登录,也就是身份认证。
三、身份认证
在UWP中,有三种方法可以调用用于身份认证(其实大同小异
• GetUniversalClient
var oneDriveClient = OneDriveClientExtensions.GetUniversalClient(scopes); var accountSession = await oneDriveClient.AuthenticateAsync();
• GetClientUsingOnlineIdAuthenticator
var oneDriveClient =await OneDriveClientExtensions.GetAuthenticatedClientUsingOnlineIdAuthenticator(scopes); var accountSession = await oneDriveClient.AuthenticateAsync();
• GetClientUsingWebAuthenticationBroker
var oneDriveClient = OneDriveClientExtensions.GetClientUsingWebAuthenticationBroker(appId,scopes); await oneDriveClient.AuthenticateAsync();
前两种方法接受一个string 数组做为参数scopes,第三者方法多一个string 参数appId。返回一个IOneDriveClient对象
scopes数组的定义是这样:
private readonly string[] scopes = new string[] { "onedrive.readwrite", "wl.offline_access", "wl.signin" };其中具体的选择可以查看这 https://dev.onedrive.com/auth/msa_oauth.htm
appId可以在注册应用的时候在应用设置中查看。我偏向于使用第一种方法,也不需要appId了。
调用oneDriveClient的AuthenticateAsync方法,如果没问题,第一次就会弹出下面的对话框
之后一般都不会再弹,除非身份验证过期。
四、SDK主要方法
OneDrive中的每一个项都是Item,因此操作的对象都是Item
1、通过Id获取Item
var item = await oneDriveClient .Items[itemId] .Request() .GetAsync();2、通过路径获取Item
var item = await oneDriveClient .Drive .Root .ItemWithPath(itemPath) .Request() .GetAsync();3、删除Item
await oneDriveClient .Drive .Items[itemId] .Request() .DeleteAsync();4、获取Item的子项目列表
var items=await oneDriveClient .Drive .Items[rootItem.Id] .Children .Request() .GetAsync(); var itemList= items.CurrentPage;5、上传Item
using (stream) { var uploadedItem = await oneDriveClient .Drive .Root .ItemWithPath(itemPath) .Content .Request() .PutAsync<Item>(stream); }6、下载Item
var stream = await oneDriveClient .Drive .Items[itemId] .Content .Request() .GetAsync();
1、XAML界面设计
<Page.Resources> <local:ItemTypeToImageConverter x:Key="ItemType2ImageConverter" /> </Page.Resources> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal" Grid.Row="0"> <Button Content="登陆" Click="btnLogin_Click" Margin="5"/> <Button Content="上传" Click="btnUpload_Click" Margin="5"/> <Button Content="下载" Click="btnDownload_Click" Margin="5"/> <Button Content="返回" Click="btnBack_Click" Margin="5"/> <TextBlock x:Name="txtMsg"/> </StackPanel> <GridView Grid.Row="1" x:Name="gridView" SelectionChanged="gridView_SelectionChanged"> <GridView.ItemTemplate> <DataTemplate> <StackPanel> <Image Source="{Binding File,Converter={StaticResource ItemType2ImageConverter}}" Width="150" Height="150"/> <TextBlock Text="{Binding Name}"/> </StackPanel> </DataTemplate> </GridView.ItemTemplate> </GridView> </Grid>
作用:如果是文件显示文件的图片,否则显示文件夹的图片。判断方式是Item的File属性是否为null
public class ItemTypeToImageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { if (value==null) return "Assets/folder.png"; else return "Assets/file.png"; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }
private async void btnLogin_Click(object sender, RoutedEventArgs e) { try { oneDriveClient = OneDriveClientExtensions.GetUniversalClient(scopes); var accountSession = await oneDriveClient.AuthenticateAsync(); if (accountSession!=null) { var rootItem = await oneDriveClient .Drive .Root .Request() .GetAsync(); var items=await oneDriveClient .Drive .Items[rootItem.Id] .Children .Request() .GetAsync(); gridView.ItemsSource = items.CurrentPage; } } catch (OneDriveException oe) { txtMsg.Text="登陆失败"; } }
判断当前选择的是否是文件夹,如果是文件夹则进入,并重新绑定数据源
private async void gridView_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (gridView.SelectedItem!=null) { var selectedItem = gridView.SelectedItem as Item; if (selectedItem.Folder!=null) { var items = await oneDriveClient .Drive .Items[selectedItem.Id] .Children .Request() .GetAsync(); gridView.ItemsSource = items.CurrentPage; pathStack.Push(selectedItem.ParentReference.Path); } } }这里用到了一个栈用来保存路径。Item的ParentReference属性是其父节点的数据
5、返回事件
如果存储路径的栈非空,说明存在上一级
private async void btnBack_Click(object sender, RoutedEventArgs e) { if (pathStack.Count >0) { var parentItem = await oneDriveClient .Drive .Root .ItemWithPath(pathStack.Pop().Substring(12)) .Request() .GetAsync(); var items = await oneDriveClient .Drive .Items[parentItem.Id] .Children .Request() .GetAsync(); gridView.ItemsSource = items.CurrentPage; } }
private async void btnUpload_Click(object sender, RoutedEventArgs e) { var picker = new FileOpenPicker(); picker.ViewMode = PickerViewMode.Thumbnail; picker.FileTypeFilter.Add(".txt"); var file = await picker.PickSingleFileAsync(); if (file != null) { Stream stream = await file.OpenStreamForReadAsync(); var uploadedItem = await oneDriveClient .Drive .Root .ItemWithPath(file.Name) .Content .Request() .PutAsync<Item>(stream); txtMsg.Text = "上传成功"; } }
毕竟是个Demo,所以只下载了跟目录下的文件
private async void btnDownload_Click(object sender, RoutedEventArgs e) { try { var picker = new FolderPicker(); picker.FileTypeFilter.Add(".txt"); var folder = await picker.PickSingleFolderAsync(); var rootItem = await oneDriveClient .Drive .Root //.ItemWithPath("焕屏") .Request() .GetAsync(); var items = await oneDriveClient .Drive .Items[rootItem.Id] .Children .Request() .GetAsync(); var queryItem = items.Where(item => item.File != null);//筛选文件 foreach (var item in queryItem) { var file = await folder.CreateFileAsync(item.Name, CreationCollisionOption.GenerateUniqueName); var stream = await oneDriveClient .Drive .Items[item.Id] .Content .Request() .GetAsync(); byte[] buffer = new byte[stream.Length]; await stream.ReadAsync(buffer, 0, buffer.Length); //将流的内容读到缓冲区 var fs = await file.OpenStreamForWriteAsync(); fs.Write(buffer, 0, buffer.Length); } txtMsg.Text = "下载成功"; } catch (Exception ex) { txtMsg.Text = "下载失败"; } }
8、运行程序,效果图
源码下载:https://github.com/hebecherish/OneDriveDemo