SharePointのREST APIを使ってファイルをダウンロードする(バッチ処理)

IT

SharePointのAPIからファイル情報を取得したり、ファイルをダウンロードする。
簡単そうなことなのに、いかんせん情報が少なかったりガセネタばかりで手こずったので、ここに詳しく記録しておく。

前提条件確認、下準備

仮に、テナント名を{{MYTENANT}}、サイト名を{{MYSITE}}としよう。
ブラウザでSharePointの画面を閲覧する際は以下のようなURLになる。

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}

「ドキュメント」をクリックすると以下のようなURLに飛ぶ。

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/Shared%20Documents/Forms/AllItems.aspx

「Shared Documents」がURLエンコードされて「Shared%20Documents」である。
このディレクトリはどのサイトにもあるだろう。

サンプルとして、以下のような階層でサブディレクトリとファイルを作成した。

Shared Documents/TestFolder/Book1.xlsx

APIのURL確認

ためしにブラウザで以下のようなURLにアクセスするとXMLで応答がある。

・フォルダ情報

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_api/web/GetFolderByServerRelativeUrl('Shared%20Documents')

・サブフォルダ一覧

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_api/web/GetFolderByServerRelativeUrl('Shared%20Documents')/Folders

・フォルダ内のファイル一覧

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_api/web/GetFolderByServerRelativeUrl('Shared%20Documents%2FTestFolder')/Files

なお、引数の値は相対パスで書くと

'Shared%20Documents'

で始まるが、絶対パスでは

'%2Fsites%2F{{MYSITE}}%2FShared%20Documents'

のように書く(「%2F」は「/」のこと)。
GetFolderByServerRelativeUrlの引数は相対パスでも問題ないようだが、GetFileByServerRelativeUrlによるファイルダウンロードの場合は絶対パスを指定しないと応答が返らなかった。

・ファイルダウンロード

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_api/web/GetFileByServerRelativeUrl('%2Fsites%2F{{MYSITE}}%2FShared%20Documents%2FTestFolder%2FBook1.xlsx')/$value

ファイルダウンロードの引数に相対パスを渡した場合、以下のようなメッセージが返った。

serverRelativeUrlParameter name: 指定した値は serverRelativeUrl  パラメーターではサポートされていません。

APIに関するマイクロソフトの公式ドキュメントは以下にある。

REST を使用してリストとリスト アイテムを操作する
SharePoint REST インターフェイスでリストとリスト アイテムに対する基本的な作成、読み取り、更新、削除 (CRUD) の操作を実行します。

API実行用アプリケーションの登録

以下のようなURLでアプリケーション登録用の画面が表示される。

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_layouts/15/appregnew.aspx

※一度作成したアプリケーションの更新・削除方法が不明なので、まず適当な値を入れてお試しするのが吉。

・クライアントID:「生成」ボタンを押せば勝手に生成される。
・クライアントシークレット:「生成」ボタンを押せば勝手に生成される。
・タイトル:任意のアプリケーション名を入力する。
・アプリドメイン:任意のドメインを入力する。「localhost」などでもよいようだ。
・リダイレクト先のURI:「http://localhost」など。

「作成」を実行すると、「アプリ ID が正常に作成されました。」という画面に遷移する。
この画面に表示されている情報を大切に保管する。

アプリケーションへの権限付与

以下のようなURLでアプリケーションへの権限付与用の画面が表示される。

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_layouts/15/appinv.aspx

・アプリID:先ほど作成したアプリケーションの「クライアントID」を入力する。
「参照」ボタンを押すと、その他の項目が補完される。

・アプリの権限要求XML:以下のような値を入れる。

<AppPermissionRequests>
    <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" />
</AppPermissionRequests>

【参考】公式サイトの説明。よくわからない。

SharePoint でのアドインのアクセス許可
アドインのアクセス許可、アクセス許可要求スコープ、およびアクセス許可の管理の種類について、ならびに、アドインのアクセス権限、ユーザー権限、Office ストア アプリ権限の相違点について説明します。

アプリの権限画面にてREALMを確認

以下のようなURLでアプリの権限が表示される。

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_layouts/15/appprincipals.aspx

アプリIDという欄に、先程のクライアントIDの後ろに「@」で区切られてハイフン区切りの36文字の文字列が続いている。この36文字がREALMである。コピーして保管する。

API実行

いよいよ、アプリからAPIを実行してみる。
APIの実行は
・アクセストークン取得
・SharePointAPI実行
の2段階の手続きを踏む必要がある。
アクセストークンの有効期限は約8時間後。一度取得すれば期限が来るまでSharePointAPI実行を繰り返すことができる。

アクセストークン取得

ここまでで取得した各値を使い、以下のようなリクエストを送信する。
・URL: https://accounts.accesscontrol.windows.net/{{REALM}}/tokens/OAuth/2
・POSTリクエスト
・HTTPヘッダに「Content-Type: application/x-www-form-urlencoded」
・リクエストボディは以下のパラメータをセットする。

grant_type=client_credentials
client_id={{クライアントID}}@{{REALM}}
client_secret={{クライアントシークレット}}
resource=00000003-0000-0ff1-ce00-000000000000/{{MYTENATNT}}.sharepoint.com@{{REALM}}

※「00000003-0000-0ff1-ce00-000000000000」はSharePointを示すprincipalという値らしい。

※Postmanなどのツールを使う場合は気にしなくてもよいが、curlなどで送信する場合は「@」や「/」をURLエンコードして「name=value&name=value&…」の形式でボディを作る。
 「@」→「%40」、「/」→「%2F」である。
 クライアントシークレットにも「/」や「=」が入っているので、忘れずにURLエンコードを行う。

※「{{MYTENANT}}.sharepoint.com」の部分を間違うと後のSharePointAPI実行で以下のようなエラーが返る。これにしばらく嵌って時間を浪費した。

{"error_description":"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}

うまくいけばJSONで応答が返ってくる。「access_token」に入っている値(長ーい文字列:これがアクセストークン)を抽出する。

SharePointAPI実行

・URL: なんでもよい。さっきブラウザで実行したAPIのURLから適当にピックアップした。

https://{{MYTENANT}}.sharepoint.com/sites/{{MYSITE}}/_api/web/GetFolderByServerRelativeUrl('Shared%20Documents')

・(上のURLの場合は)GETリクエスト
・HTTPヘッダに「Authorization: Bearer {{アクセストークン}}」
・HTTPヘッダに「Accept: application/json;odata=nometadata」

うまくいけば、欲しかった情報が返ってくるはず。

以上


【参考サイト】

REST を使用してリストとリスト アイテムを操作する
SharePoint REST インターフェイスでリストとリスト アイテムに対する基本的な作成、読み取り、更新、削除 (CRUD) の操作を実行します。
Sharepoint Online Authentication for API Access using POSTMAN
Objective: We know most of the collaboration part of sharepoint has been pushed to Teams, with its planner, conversations, a dedicated sit...

コメント

  1. ひげ より:

    “アプリケーションへの権限付与” の項で
    「・アプリの権限要求XML:以下のような値を入れる。」とありますが
    入れる値の記載が抜けているようです。

    • ichiro より:

      ご指摘ありがとうございます。追記しました。
      ずっとメンテナンスをサボっていました。

  2. SEO Affiliate より:

    Awesome post! Keep up the great work! 🙂