[補足資料] SharePointOnline から特定のフォルダ以下のファイルをすべてBlob Storageにコピーする方法
Azure Data Factory/Azure Synapse Pipelineは、Cloud上のSparkクラスターで膨大なデータをD&DのGUIベースで設計し、処理することができます。
この記事の対象者は、Azure Data Factoy(Synapse Pipeline)でアクティビティを用いてパイプライン実行をしたことがある方を対象としております。そうでいない方は、以下の記事をご参考ください。
- Azure Data Factoryのクイックスタートについてこちらを参照ください
- Azure Data Factoryについてより理解を深めたい方は充実したこちらのYouTubeチャンネルをご覧ください。
- Azure Data FactoryとSynapse Pipelineは、ほぼ近しいサービスであるが、違いについて知りたい方は以下のサイトを参照ください。
はじめに
実装したいことはシンプルで、SharePoint上にあるフォルダを対象に複数ファイルをAzure Blob Storageにコピーすることです。この一連の流れはSharePointヘビーユーザ企業には需要があることは確認されており、インターネット上でチャレンジしては、エラーを出力され、問題が解決されていない掲示板の声は多いです。
Microsoftはこの一連の流れを記事にしており、参考に実装を勧めたが、つまづくポイントが多く、表記ゆれや最後まで説明されていない箇所が存在した。特に、ファイル名がランダムな文字列となり、予期した挙動にならなかった。
そこで、本記事では日本語スピーカーを対象にMicrosoftが公開しているTechCommunityの資料の補助として情報を残します。
▼Microsoft Tech Communityが公開している記事
本記事に関するリソース
Azure Data Factoryのソース管理機能に基づいて、リポジトリが構成されております。
メンテナンス中
▼本記事の内容を実装したソースコード
https://github.com/hogaku/sharepoint_in_adf
▼本記事で仕様したテストデータ(githubリポジトリ上にあり)

▼MSTechCommunityの記事(本記事の被補助記事)
手法
以下に示す3ステップにより実現します。
- Webアクティビティを用いて、SharePointOnlineからアクセストークンを取得します(アクティビティ名:Web1)。
- 2つ目のWebアクティビティを用意し、SPO上のフォルダからファイルの一覧を取得(アクティビティ名:Web2)
- ForEachアクティビティとデータのコピーアクティビティを用いて、フォルダ内のファイルリストをループし、随時、データをコピー(SharePoint→Azure Blob Storage)(ForEachアクティビティ名:ForEach1, データのコピーアクティビティ名:CopyData1)。

Fig.1 全体のパイプラインフロー

Fig.2 ForEachアクティビティの内部アクティビティ
Step1: Grab Access token from SPO(SPOからのアクセストークンの取得)
こちらのStepでは、SharePointAPIを利用してファイルを取得するために、AADアプリの登録と登録したアプリからのSharePointサイトへのアクセス許可するための手続きを行います。初めての方は用心深くなるかもしれませんが、示されている通りに手順を踏めば特に問題ないでしょう。一応、軽く示します。
「a) AAD アプリケーションの登録」に関して
- まずはこちらのAzure PortalのMicrosoft|アプリの登録へアクセスし、[+新規登録]ボタンをクリック後、↓のリンクへアクセスし、アプリケーションの登録を行いましょう。
▼アプリケーションを Azure AD テナントに登録する
※MSTechCommunityの記事では、英語の記事がリンクとして掲載されているため、改めて、日本語ページを掲載しておきます。
- 次にこのように項目を埋めてください(一番上の名前の部分は適当につけてください。アプリのリストの画面で表示されます)。

Fig.3 アプリケーションの登録画面
- 登録されたアプリのページに遷移し、「証明書とシークレット」に移動し、新しいクライアントシークレットを作成します。
後程、次の画像の「概要ページ」に示されている「アプリケーション (クライアント)ID」、「オブジェクト ID」、「ディレクトリ (テナント) ID」と、「証明書とシークレット」に示されている「値」をWebアクティビティの設定で利用します。

Fig.4 登録されたアプリの概要ページ

Fig.5 登録されたアプリの証明書とシークレットページ
「b) 登録されたアプリに SharePoint サイトのアクセス許可を付与する(SharePoint のサイト所有者のアクセス許可が必要)」に関して
こちらは画像が1枚張られ、詳細はこちらのリンクを参照ということで、再び英語ページのリンクのため、日本語ページを掲載しておきます。
リンク先を踏むと、前提条件の1に先ほどのAADへのアプリの登録に関して記載があり、2.登録した~からとなります。
SharePointOnlineサイトの管理ページへアクセスします。
https://[your_site_url]/_layouts/15/appinv.aspx

Fig.6 SharePoint上のHome画面
参考資料:SharePoint Online の直打ちURL集
上手くいくとこのような管理ページにアクセスすることができます。

Fig.7 SharePointの管理ページ
あとはドキュメントにも記載がありますが、以下の通りに入力すればOKです。
| 項目名 | 設定内容 |
|---|---|
| アプリ ドメイン | localhost.com |
| リダイレクト URL | https://www.localhost.com |
| 権限の要求 XML | ↓以下に示す |
<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="Read"/>
</AppPermissionRequests>
「c) ADF パイプラインを作成します。 Web アクティビティの作成から開始してアクセス トークンを取得する」に関して
設定内容を示します。
| 項目名 | 設定内容 |
|---|---|
| URL | https://accounts.accesscontrol.windows.net/[ディレクトリ (テナント) ID]/tokens/OAuth/2 |
| メソッド* | POST |
| ヘッダー*(名前) | Content-Type |
| ヘッダー*(値) | application/x-www-form-urlencoded |
| 本文 | 便宜上、↓に示す。コピーして[]の部分を書き換えてください(カッコは不要)。 |
※ 2023.03時点でgrant_typeの書き方に変化があったようです。
grant_type=client_credentials&client_id=[Client-ID]@[Tenant-ID]&client_secret=[Client-Secret]&resource=00000003-0000-0ff1-ce00-000000000000/[Tenant-Name].sharepoint.com@[Tenant-ID]

Fig.8 アプリケーションの登録画面
Step2: Get the list of Files(ファイルの一覧を取得する)
こちらのStepでは、Step1で取得したSPOのトークン情報を用いて、SPO上のファイル情報を取得します。ここのWebアクティビティでは、こちらのRest APIをコールしております。
| 項目名 | 設定内容 |
|---|---|
| URL | 便宜上、↓に示す。コピーして[]の部分を書き換えてください(カッコは不要)。 |
| メソッド* | GET |
| ヘッダー1つ目*(名前) | Authorization |
| ヘッダー1つ目*(値) | @{concat('Bearer ', activity('Web1').output.access_token)} |
| ヘッダー2つ目*(名前) | Accept |
| ヘッダー2つ目*(値) | application/json |
https://microsoftapc.sharepoint.com/teams/SPOinADF/_api/web/GetFolderByServerRelativeUrl('Shared Documents/フォルダ名')/Files
デバッグ実行し、Fig.9に示すWeb2の出力をクリックすると出力画面でこのようにファイルのパスや、作成日等を取得することができます。こちらの画面で正しい情報が取得できているのかの確認をすることができます。

Fig.9 パイプライン実行の出力画面

Fig.10 Web2の出力結果画面
Step3: Loop the list of relative file names(相対ファイル名のリストをループする)
こちらのStepでは、Step2で取得したSPOのファイルリストの内容を取得して、内部でコピー処理するためのアクティビティを用意します。ここは一番シンプルで、設定する内容は次の1つのみで注意点も特にないかと思います。

Fig.11 ForEachアクティビティの設定内容

| 項目名 | 設定内容 |
|---|---|
| 順次 | チェックあり |
| 項目 | @activity('Web2').output.value |
設定が完了したら、ForEachアクティビティをダブルクリックし、データのコピーアクティビティを配置しましょう。

Fig.12 ForEachアクティビティ内部に設置されたコピーアクティビティ
Step4:Create Copy activity(コピーアクティビティを作成)
Step名にCreate Copy activityと書かれていますが、実際は設定のみですね。
一番ここのStepの設定が混乱します。
ソース
まずは、こちらに既に設定済みの画面を示します。

Fig.13 データのコピーアクティビティのソース設定
| 項目名 | 設定内容 |
|---|---|
| ソースデータセット | 次、説明! |
| RelativeURL | @{item().ServerRelativeUrl} |
| 要求メソッド* | GET |
| 追加のヘッダー | @{concat('Authorization: Bearer',activity('Web1').output.access_token)} |
既に設定されているが、正しく動作していない前提でチェックポイントとして記述します。
上から見ていきましょう。まずは、ソースデータセットです。ここでは、手順通り、HTTPのコネクタを選択しバイナリ項目で作成されていることをまず確認してください。

Fig.14 ソースデータセットの設定値
| 項目名 | 設定内容 |
|---|---|
| リンクサービスのプロパティ(名前) | FileName |
| リンクサービスのプロパティ(値) | @dataset().RelativeURL |
パラメータとして、RelativeURLという名前で指定します。ここで指定した文字列が、@dataset().RelativeURLとして扱うことができます。
▼参考資料

Fig.15 ソースデータセットのパラメータ値
| 項目名 | 設定内容 |
|---|---|
| 名前 | RelativeURL |
| 種類 | 文字列 |
| 既定値 | abc |
そして、具体的にどうやって、このRelativeURLの値を決めているかというと、Fig.13のソースデータセットのプロパティでRelativeURLの値で決めています。@{item().ServerRelativeUrl}と記述しましたが、これはFig.10に示すWeb2アクティビティで取得したファイル情報に書かれている「ServerRelativeUrl」の値を参照しており、このようにitem().○○でこの値を取得しセットします。
シンク
次は、シンク設定をチェックして行きましょう。

Fig.16 データのコピーアクティビティのシンク設定
こちらも、データセットのプロパティでFileNameを指定し、値を@item.Nameで取得しています。
シンクデータセットの中身はこのようになっています。

Fig.17 シンクデータセットの設定値
| 項目名 | 設定内容 |
|---|---|
| リンクサービス | 次に説明 |
| ファイルパス | [コンテナ名(適当に記入)]/ディレクトリ名/@dataset().FileName |
| 圧縮の種類 | なし |
そして、パラメータ値はこのようになります。

Fig.18 シンクデータセットのパラメータ値
ソースの設定と大体一緒ですね。データセットにパラメータを持たせて、SPOから取得したファイルリストのFileNameの値をセットしてコピーしたバイナリデータに名前を付けています。改めて、Fig.10に示すWeb2アクティビティで取得した情報を確認するとばっちりNameの文字列があることが分かると思います。こちらのデータを参照しています。
パイプラインの実行
デバッグボタンをクリックして、実行すると以下のような結果が得られたら成功です。CopyData1が4つあるのは4ファイル分処理をしたということですね。

Fig.19 実行結果画面の確認
4つのテストファイルは、画像ファイル、テキストファイル(文字化け確認用に日本語・英語記述)、パワポファイル、圧縮ファイルを用意してテストしました。
結果、Blob Storageには4つのファイルが生成され、ダウンロードして問題なく開けることを確認しました。

Fig.20 Blob Storageの中身の確認
参考資料
- Azure Data Factory または Azure Synapse Analytics を使用して SharePoint Online リストからデータをコピーする
- SharePoint Online Multiple Files (Folder) Copy with Http Connector
- How to read files on SharePoint Online using Azure Data Factory
- SharePoint File Copy to Azure using Power Automate or Azure Data Factory
- Azure Data FactoryでSharePointのファイルをADLS Gen2にコピー
最後に
本記事では、Microsoft Tech Communityの記事を基に補助説明を加えたものになります。SharePoint上のファイルをStorageにコピーする方法としてAzure Data Factoryを用いましたが、同様のことは、こちらの記事のようにAzure Logic Appsでも実現することができます(その違いに関しては気になる方がおりましたら、加筆するかもしれません)。
お読み頂きましてありがとうございました😊
ご質問やご感想などありましたら、ぜひTwitter (@shisyu_gaku) までお気軽にお問い合わせください。
Discussion