はじめに

SharePointは、社内ドキュメントの管理やファイル共有の基盤として広く利用されていますが、外部システムやバッチ処理からファイルを自動で連携したいケースも多くあります。

例えば、以下のようなユースケースがあります。

  • 業務システムで生成した帳票をSharePointに自動保存する
  • バッチ処理で作成されたログやレポートを定期的にアップロードする
  • 外部サービスから受け取ったファイルをSharePointにに集約する

Microsoft Graphは、Microsoft365(ユーザー、メール、ファイル、Teamsなど)のデータや機能に、統一されたAPIでアクセスできるプラットフォームです。

また、アプリケーション認証を利用することで、ユーザー操作を介さずにバックエンド処理から安全にファイル連携を行うことが可能になります。

本記事では、これらの背景を踏まえ、Microsoft Graphを用いてSharePointへファイルをアップロードする具体的な方法を解説します。

前提

本記事のサンプルコードは、C#(.NET 10.0)で実装しています。
また、認証にはアプリケーション認証(証明書)を使用し、Microsoft Entra IDに登録したアプリケーションからGraph APIへアクセスします。
今回、証明書は自己署名証明書を使用します。

手順

Microsoft Entra 管理センターでアプリ登録

アプリからGraph APIを呼び出すためには、事前にMicrosoft Entra 管理センターにてアプリの登録を行う必要があります。

アプリ登録

手順:Microsoft Entra ID でアプリを登録する方法

アプリ登録が完了したら、
・アプリケーション(クライアント)ID
・ディレクトリ(テナント)ID
を控えておきます(アプリからGraph APIを呼び出す際に必要になる)。

資格情報の追加

次はアプリに資格情報を追加します。
手順:Microsoft Entra ID でアプリの資格情報を追加および管理する

証明書を追加しました。

APIのアクセス許可

最後にAPIのアクセス許可を設定します。
手順:Microsoft Entra ID でアプリの要求されたアクセス許可を更新する

ファイルのアップロードを行うため、書き込み権限(write)が必要です。
「Sites.〇〇」はSharePointのサイトに対するアクセス許可を表します。

一見「Sites.ReadWrite.All」が適切ですが、これは対象テナント内のすべてのサイトを対象とするアクセス許可です。
特定のサイトへのアクセス許可を与えたい場合は、「Sites.Selected」が適切です。
今回は「Sites.Selected」を選択します。

「Sites.Selected」を選択した場合は、どのサイトに対するアクセス許可を付与するか別途設定する必要があります。
この設定はGraph ExplorerまたはPowerShellで行うことができ、今回はGraph Explorerで設定します。

※サブサイトに対するアクセス許可はGraph Explorerでは設定できないため、PowerShellで設定する必要があります。

Graph Explorerでアクセス許可の設定と必要な情報取得を行う

Graph Explorerは、ブラウザ上からMicrosoft Graph APIを実際にリクエストを実行して動作を確認できるテストツールです。
概要:Graph エクスプローラーを使用して Microsoft Graph API を試す

Graph Explorerを使ってSharePointに対するアクセス許可の設定と、必要な情報の取得を行います。
まずはGraph Explorerにアクセスし、対象サイトの管理権限があるアカウントでサインインします。

サイトIDの取得

アクセス許可の設定とドライブIDの取得にはサイトIDが必要となるため、先にサイトIDを取得します。

サイトIDを取得するために、まずはサイト名を確認します。
サイト名はサイトのURLから確認できます。「sites/」の後ろがサイト名です。

サイト名を確認したら、Graph ExplorerでサイトIDを取得します。

https://graph.microsoft.com/v1.0/sites?search={サイト名}

アクセス許可の設定

「Sites.Selected」を選択したので、対象サイトに対する書き込み権限を付与します。
手順:Microsoft Graph と SharePoint Online のリソース固有の同意について

こちらのURLにPOSTリクエストを行います。

https://graph.microsoft.com/v1.0/sites/{サイトID}/permissions

リクエストボディは下記のように設定します。
ファイルのアップロードが目的のため、「ロール」には「write」を記載します。

{
  "roles": ["{ロール}"],
  "grantedToIdentities": [{
    "application": {
      "id": "{クライアントID}",
      "displayName": "{アプリケーション名}"
    }
  }]
}

POSTリクエストを実行する。

GETリクエストで権限が付与されていることを確認する。

ドライブIDの取得

SharePointのアップロード先を指定するために、Graph Explorerを使用してドライブIDを取得します。

サイトIDを使用して、ドライブIDを取得する。

https://graph.microsoft.com/v1.0/sites/{サイトID}/drives

ドライブIDが取得できました。
これで準備が整ったので、実装していきます。

実装

準備

Microsoft Graph SDKをインストールしておきます。
概要:Microsoft Graph SDK の概要

証明書の取得

Entra管理センターで追加した証明書に対応するpfx証明書を取得します。
今回は現在のユーザーの証明書ストアにpfx証明書を保持しています。

using var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);

// フレンドリー名 で完全一致検索
X509Certificate2? cert = store.Certificates
    .Cast<X509Certificate2>()
    .FirstOrDefault(x => x.FriendlyName == {フレンドリー名});

GraphServiceClientを作成

アプリ登録時に確認した
・テナントID
・クライアントID
と取得した証明書を使用してClientCertificateCredentialを作成します。

作成したClientCertificateCredentialを引数に、GraphServiceClientを作成します。

credential = new ClientCertificateCredential({テナントID}, {クライアントID}, cert);

graphServiceClient = new GraphServiceClient(credential);

ファイルをアップロード

小さいファイルの場合

ファイルサイズが小さい場合は、下記のようにアップロードします。

var uploadedItem = await graphServiceClient
    .Drives[{ドライブID}]
    .Root
    .ItemWithPath({アップロード先のパス})
    .Content
    .PutAsync({ファイルストリーム})

大きいファイルの場合

大きいファイルの場合は、アップロードセッションを使用します。
参考:Microsoft Graph SDK を使用して大きなファイルをアップロードする

var uploadSessionRequestBody = new DriveUpload.CreateUploadSessionPostRequestBody
{
    Item = new DriveItemUploadableProperties
    {
        AdditionalData = new Dictionary<string, object>
        {
            { "@microsoft.graph.conflictBehavior", "replace" },
        },
    },
};

var uploadSession = await graphServiceClient
    .Drives[{ドライブID}]
    .Root
    .ItemWithPath({アップロード先のパス})
    .CreateUploadSession
    .PostAsync(uploadSessionRequestBody);

int maxSliceSize = 320 * 1024;
var fileUploadTask = new LargeFileUploadTask<DriveItem>(
    uploadSession, {ファイルストリーム}, maxSliceSize, graphClient.RequestAdapter);

var totalLength = fileStream.Length;

IProgress<long> progress = new Progress<long>(prog =>
{
    Console.WriteLine($"Uploaded {prog} bytes of {totalLength} bytes");
});

try
{
    var uploadResult = await fileUploadTask.UploadAsync(progress);

    Console.WriteLine(uploadResult.UploadSucceeded ?
        $"Upload complete, item ID: {uploadResult.ItemResponse.Id}" :
        "Upload failed");
}
catch (ODataError ex)
{
    Console.WriteLine($"Error uploading: {ex.Error?.Message}");
}

おわりに

以上で、Microsoft Graphを利用したSharePointへのファイルアップロードの手順を一通り確認できました。用途に応じてアクセス許可やアップロード方法を適切に選択し、効率的なファイル連携を実現していきましょう。