【Functions】GraphAPIを使ってSharePointへファイルアップロードする

2025年5月11日JavaScript,環境構築

こんにちは、しきゆらです。
今回は、Azure FunctionsからGraph APIを使ってSharePointへファイルをアップロードさせる方法をメモしておきます。

これまで何件かAzure Functions関連の記事を書いていましたが、今回がひとまずの最後です。
Azure FunctionsからSharePointへファイルアップロードする方法です。
用途としては、例えばFunctionsで何らかの処理をした結果を格納、とかでしょうか。

では、手順をまとめます。

クレデンシャルの作成

Entra IDにアプリを登録し、クライアントID/シークレットを取得して、これを使ってAPIを呼び出す形になります。
参考になりそうなのはこの辺。

アプリの登録

Entra IDにログインし、管理>アプリの登録からアプリの新規登録を行います。

適当な名前を付け、認証する種類を選択して作成します。
ここでは「この組織ディレクトリのみに含まれるアカウント」を選んでいます。

作成に成功すると下図のような画面になります。
ここの「アプリケーション(クライアント)ID」がそのままクライアントIDとなります。
合わせてディレクトリ(テナント)IDも必要になるので、覚えておきましょう。

クライアントシークレットを作成する

アプリを作成出来たら「管理」>「証明書とシークレット」から作成します。

シークレットの用途等を説明欄に記入し、シークレットの有効期限を適宜設定して作成します。
シークレットは作成したタイミングのみしか表示されないので、忘れずにコピーしておきましょう。
なお、わからなくなっても作り直せばよい。

これにて、クライアントID・シークレット・テナントIDが用意できました。

APIアクセス許可

アプリの作成ができたら、APIアクセスの許可をしてあげる必要があります。
いわゆるAPIのスコープを設定していきます。

参考になりそうなのは、以下あたり。

アクセス方法として、ユーザの代わりにアクセスする「委任アクセス」とユーザが関与しない「アプリ専用アクセス」の2種類があります。
今回は、Azure FunctionsからAPIアクセスするのでユーザではなくアプリ専用アクセスの方なので、その手順で設定していきます。

参考となるのはこの辺あたり。

スコープの確認

呼び出すAPIが必要とするスコープを確認しましょう。
スコープの一覧は以下にあります

ただし、上記を見てもどれがどれなのかいまいちわかりにくいので、これよりも各サービス・APIのページを確認した方が確実かと思います。

今回は、API経由でSharePointへファイルアップロードしたいので、以下からスコープを確認。

Files.ReadWrite.AllSites.ReadWrite.Allが該当するようです。
ここでは面倒なので両方設定していきます。

スコープに対して許可する

アプリの「管理」>「APIアクセス許可」を開き「アクセス許可の追加」を開きます。

Graph APIを使うのでMicrosoft Graphを選択しますが、具体的なサービスからも設定可能です。

「アプリケーションの許可」を選択し、先ほど確認したスコープにチェックを入れます。
検索も可能。

追加後、リストに表示されます。
「管理者の同意が必要」が「はい」となっている場合は「<テナント名>に管理者の同意を与えます」をクリック。
なお、ここはテナント管理者の権限が必要そうです。

同意できるとチェックマークがつくので確認しましょう。

これにて設定完了です。

実装

では実際にコードを書いていきます。
まずはライブラリのインストールから。

ライブラリ追加

Graph APIのSDKと認証用のライブラリを追加します。

yarn add @microsoft/microsoft-graph-client @azure/identity
Bash

追加出来たら、コード書いていきます。

アップロードするAPIの確認

スコープを確認したページに書いてあるので確認しておきます。

いくつかあるようですが、今回は以下を選択。

PUT https://graph.microsoft.com/v1.0/sites/SiteID/drive/root:/path/to/Dir/fileName:/content

追加で確認が必要なのはSiteID。

サイトIDを確認

参考になりそうなのはこの辺かと。

コードからAPI叩いて結果を確認するのでもよいですが、Graph Editorを入れてGUI上で確認するのが楽でした。

以下のような形でサイトで検索して、IDを取得しましょう。

GET https://graph.microsoft.com/v1.0/sites?search=hogehoge

結果が以下のような形で返ってきます。
value配下の1要素が1サイトを表していて、そのIDがサイトIDです。
3つの値がカンマで並んでいる形ですが、3つ合わせてIDのようです。

{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites",
  "value": [
    {
      "createdDateTime": "2025-05-14T10:21:05Z",
      "id": "<tenant>.sharepoint.com,xxxxxxxxxxxxx,xxxxxxxxxxxxxxx",
      "lastModifiedDateTime": "2025-05-14T10:21:08Z",
      "name": "name",
      "webUrl": "https://<tenant>.sharepoint.com/sites/aaaaa",
      "displayName": "サイトの表示名"
    },
    {
      "createdDateTime": "2025-04-26T02:39:58Z",
      "id": "<tenent>.sharepoint.com,xxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxxxx",
      "lastModifiedDateTime": "2025-04-26T02:40:06Z",
      "name": "NAME",
      "webUrl": "https://<tentn>.sharepoint.com/sites/hogehoge",
      "displayName": "サンプルサイト",
      "root": {},
      "siteCollection": {
        "hostname": "<tenant>.sharepoint.com"
      }
    }
  ]
}
JSON

コード

ざっくり以下のような感じ。

import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
import { ClientSecretCredential } from "@azure/identity";
import { Client } from "@microsoft/microsoft-graph-client";
import { TokenCredentialAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials';

const tenantId = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
const clientId = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
const clientSecret = 'xxxxxxxxxxxxxxxxxxxxx';

const folderPath = "/sites/<SiteID>/drive/root:/path/to/directory";

const httpTrigger1 = async (request: HttpRequest, context: InvocationContext) => {
    try {
        const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
        const authProvider = new TokenCredentialAuthenticationProvider(credential, {
            scopes: ["https://graph.microsoft.com/.default"]
        });

        const client = Client.initWithMiddleware({
            authProvider: authProvider,
            debugLogging: true,
        });
        const fileName = `result_${Date.now()}.txt`;
        const fileContent = JSON.stringify(request.body);

        await uploadFileToSharePoint(client, fileName, fileContent);

        return { status: 200, body: `File uploaded successfully: ${fileName}` };
    } catch (e) {
        context.log("Error:", e);
        return { status: 500, body: "Internal Server Error" };
    }
}

const uploadFileToSharePoint = async (graphClient: Client, fileName: string, fileContent: string): Promise<void> => {
    try {
        console.log(`uploadPath ==> ${folderPath}/${fileName}:/content`)
        const result = await graphClient.api(`${folderPath}/${fileName}:/content`)
            .put(fileContent);
        console.log("File upload result:", result);
        console.log(`File uploaded: ${folderPath}/${fileName}`);
    } catch (e) {
        console.log("Error uploading file:", e);
        throw e;
    }
}

app.http('httpTrigger1', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: httpTrigger1
});
JavaScript

ざっくり解説すると、以下の部分が認証とAPIをたたくクライアント作成周り。
参考となるのはこの辺。

テナントID・クライアントID・シークレットをClientSecretCredentialに食わせてTokenProviderを作成。
作成したTokenProviderClientの初期化時に渡してクライアントを作成します。

const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
const authProvider = new TokenCredentialAuthenticationProvider(credential, {
    scopes: ["https://graph.microsoft.com/.default"]
});
const client = Client.initWithMiddleware({
    authProvider: authProvider,
    debugLogging: true,
});
JavaScript

クライアントが作成出来たら、APIをたたきましょう。
今回は、アップロード部分は別関数に分けています。
処理に関する部分はこの辺。

const folderPath = "/sites/<SiteID>/drive/root:/path/to/directory";
...
const result = await graphClient.api(`${folderPath}/${fileName}:/content`)
    .put(fileContent);
JavaScript

確認したAPI/サイトIDをもとに変数folderPathを定義。
このパスに対してファイル名を合わせてAPIを実行します。
putメソッドの引数としてファイルの内容を渡しています。

実行すると以下のような感じでファイルが作成されるはずです。

今回はテストとしてコードを書いているので、クレデンシャルを直書きしています。
動作確認ができたら、クレデンシャル情報は例えばKeyVaultに格納して環境変数として参照するなどしましょう。

Azure FunctionsからKeyValutの値を参照する方法は以前メモしているので、こちらも併せてご確認ください。

まとめ

今回はAzure FunctionsからGraph APIを使ってSharePointへファイルをアップロードする方法をメモしました。

SharePointのAPIをほかのものに置き換えれば、MSのサービス・データを参照した処理を実装可能になるかと思います。
そのベースとなる部分をふれられたので今回は満足です。

今回は、ここまで。

おわり

Posted by しきゆら