3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Microsoft Graph で Microsoft 365 SharePoint サイトのドキュメントを取得する

Posted at

Microsoft Graph API を使って、Microsoft 365 の SharePoint のドキュメントを取得するときに、 {site-id} がわかりにくかったのでメモを残します。

Microsoft Graph を使用して、OneDrive、OneDrive for Business、および SharePoint のドキュメント ライブラリに配置されるファイルに接続するアプリケーションを作成する場合、以下のドキュメントが参考になります。

Azure Active Directory にアプリケーション登録

前回記事「Microsoft Graph で Microsoft 365 Enterprise 組織内のメールを取得する」の「Azure Active Directory にアプリケーション登録」を参考に、アプリケーション登録を行ってください。今回は「Files.Read.All」と「Sites.Read.All」を使います。

00.png

SharePoint にサイトを作成してファイルをアップロード

SharePointにサイトを作成します。今回は「Communication Site」を選択しました。(既にSharePointサイトをお持ちの方は次の章にスキップしてください。)

01.png

デザインは「Topic」、サイト名を「azure」で作成しました。

02.png

完成したサイトの「Documents」を選択します。

03.png

Documentsにファイルをアップロードしておきます。

04.png

バックグランドサービスとして動くアプリを作成

前回記事「Microsoft Graph で Microsoft 365 Enterprise 組織内のメールを取得する」の「バックグランドサービスとして動くアプリを作成」と同じようにプログラムを作成します。

注意点としては、/sites/{site-id} を使用して取得した別のサイトIDを使用して /sites/{site-id}/drive などにアクセスします。なお、初めに使用する /sites/{site-id} の {site-id} は、"{hostname}:/{server-relative-path}" のようなフォーマットになります。

GraphHelper.cs
using Microsoft.Graph;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace GraphFileSample
{
    public class GraphHelper
    {
        private static GraphServiceClient graphClient;
        public static void Initialize(IAuthenticationProvider authProvider)
        {
            graphClient = new GraphServiceClient(authProvider);
        }

        public static async Task<Site> GetSiteAsync(string siteId)
        {
            // siteId format is "{hostname}:/{server-relative-path}"
            try
            {
                var site = await graphClient.Sites[siteId].Request().GetAsync();
                return site;
            }
            catch (ServiceException ex)
            {
                Console.WriteLine($"Error getting events: {ex.Message}");
                return null;
            }
        }

        public static async Task<IEnumerable<DriveItem>> GetDriveRootChildrenAsync(string siteObjId)
        {
            // siteObjId format is "xxxxxxxx,xxxxxxxxx,xxxxxxxxx"
            try
            {
                List<DriveItem> dirobjects = new List<DriveItem>();
                var resultPage = await graphClient.Sites[siteObjId].Drive.Root.Children.Request().GetAsync();
                while (true)
                {
                    dirobjects.AddRange(resultPage);
                    if (resultPage.NextPageRequest == null)
                    {
                        break;
                    }
                    resultPage = resultPage.NextPageRequest.GetAsync().Result;
                }
                return dirobjects;
            }
            catch (ServiceException ex)
            {
                Console.WriteLine($"Error getting events: {ex.Message}");
                return null;
            }
        }
        public static async Task<Stream> GetDriveContentAsync(string siteObjId, string itemId)
        {
            // siteObjId format is "xxxxxxxx,xxxxxxxxx,xxxxxxxxx"
            try
            {
                var result = await graphClient.Sites[siteObjId].Drive.Items[itemId].Content.Request().GetAsync();
                return result;
            }
            catch (ServiceException ex)
            {
                Console.WriteLine($"Error getting events: {ex.Message}");
                return null;
            }
        }
        
    }
}

作成したGraphHelper.csを使用して、SharePointのサイトの、ドキュメントのルートに存在するファイルを全てダウンロードします。

Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Graph;

namespace GraphFileSample
{
    class Program
    {
        static Dictionary<string, string> LoadClientSecretAppSettings()
        {
            Dictionary<string, string> result = null;
            // Get config ftom AppSettings
            var appConfig = new ConfigurationBuilder()
                .AddUserSecrets<Program>()
                .Build();
            var appId = appConfig["appId"];
            var scopes = appConfig["scopes"];
            var tenantId = appConfig["tenantId"];
            var clientSecret = appConfig["clientSecret"];
            var siteId = appConfig["siteId"];
            if (string.IsNullOrEmpty(appId) == false &&
                string.IsNullOrEmpty(scopes) == false &&
                string.IsNullOrEmpty(tenantId) == false &&
                string.IsNullOrEmpty(clientSecret) == false &&
                string.IsNullOrEmpty(siteId) == false)
            {
                result = new Dictionary<string, string>()
                {
                    {"appId", appId},
                    {"scopes", scopes},
                    {"tenantId", tenantId},
                    {"clientSecret", clientSecret},
                    {"siteId", siteId}
                };
            }
            return result;
        }

        static void GetSiteDocuments(string siteId)
        {
            var site = GraphHelper.GetSiteAsync(siteId).Result;
            var items = GraphHelper.GetDriveRootChildrenAsync(site.Id).Result;
            foreach (var item in items)
            {
                Console.WriteLine($"Entity.Id: {item.Id}");
                Console.WriteLine($"BaseItem.File: {item.Name}");
                using (var itemContent =  GraphHelper.GetDriveContentAsync(site.Id, item.Id).Result)
                using (var fileStream = new FileStream(item.Name, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    itemContent.CopyTo(fileStream);
                }
            }
        }

        static void Main(string[] args)
        {
            IAuthenticationProvider authProvider = null;

            var appConfig = LoadClientSecretAppSettings();
            if (appConfig == null)
            {
                Console.WriteLine("Missing or invalid AppSettings");
                return;
            }
            var appId = appConfig["appId"];
            var scopesString = appConfig["scopes"];
            var scopes = scopesString.Split(';');
            var tenantId = appConfig["tenantId"];
            var clientSecret = appConfig["clientSecret"];
            var siteId = appConfig["siteId"];
            // Initialize the auth provider
            authProvider = new ClientSecretAuthProvider(appId, scopes, tenantId, clientSecret);
            // Initialize Graph client
            GraphHelper.Initialize(authProvider);
            // Get Files
            GetSiteDocuments(siteId);
        }
    }
}

実行する

上で書いたコードは、githubにおいてあるので、cloneします。

git clone https://github.com/KentaroAOKI/GraphFileSample.git
cd GraphFileSample

Azure Active Directory でアプリケーション登録をした際にメモした値を使って設定します。

dotnet user-secrets init
dotnet user-secrets set appId "{アプリケーション(クライアント)ID}"
dotnet user-secrets set scopes "https://graph.microsoft.com/.default"
dotnet user-secrets set tenantId "{ディレクトリ(テナント)ID}"
dotnet user-secrets set clientSecret "{クライアントシークレット}"
dotnet user-secrets set siteId "{テナント}.sharepoint.com:/sites/{サイト}"

今回作成した SharePoint サイトの siteId は、"xxxxx.sharepoint.com:/sites/azure" になります。

ビルドして実行すると、JAZUG(5).pptx がローカルにダウンロードされます。

dotnet build
dotnet run

さいごに

Graph API のサイトIDで、かなり時間をかけてしてしまいましたが、知っていれば簡単に自分のアプリで使えそうです。
Microsoft 365との連携は色々面白いことができそうなので、引き続き他の機能も試していきたいです。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?