3
1

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 1 year has passed since last update.

Azure Data FactoryでSharePointのファイルをADLS Gen2にコピー

Last updated at Posted at 2021-03-23

やりたいこと

  • SharePointOnline(SPO)の特定のフォルダ内にあるファイルをゴソっとAzure Data Lake Storage Gen2(ADLS Gen2)にコピーしたい
  • MSドキュメントに1ファイルだけコピーする方法が紹介されていたので、これを参考にやってみます

Azure AD にアプリケーションを登録

Azure Portalから、Azure Active Directory > アプリの登録 > 新規登録

image.png

アプリケーションIDとテナントIDをコピーしておきましょう

image.png

続いて、このアプリケーションのシークレットを発行します
証明書とシークレット > 新しいクライアントシークレット
クライアントシークレットが作成されたら、をコピーします

image.png

アプリケーションにSPOサイトのアクセス許可を付与

SharePoint上での作業です
アプリに権限を付与するために、以下のページを開きます
<tenant_name><site_name>は環境に合わせて変更します

https://<tenant_name>.sharepoint.com/sites/<site_name>/_layouts/15/appinv.aspx

image.png

アプリIDに先程コピーしたIDを貼り付けて、参照ボタンを押すとタイトルに登録したアプリ名が自動で設定されます。アプリ ドメインリダイレクト先のURL権限の要求XML冒頭のMSドキュメントの通り入力します

image.png

信頼します

これで、Data FactoryからSPOにアクセスするために利用するアプリが作成できました

ちなみに、SharePoint REST APIに関するページを見ると、https://{site_url}/_api/web/...といった形でリクエストするURLが記載されていますが、{site_url}の部分が<tenant_name>.sharepoint.com/sites/<site_name>です

Data Factoryでパイプラインを作成

パイプラインの完成形

ここから長くなるので、先に完成形をお見せしておきます

image.png

Webアクティビティ:SPOのアクセストークンを取得

以下の通り設定します
<app_id><app_secret><tenant_id><tenant_name>は置き換えてください
ドキュメントに記載がありますが、セキュリティで保護された出力をONにしているのは、シークレットの値がログに出力されないようにするためです

  • URL: https://accounts.accesscontrol.windows.net//tokens/OAuth/2
  • メソッド: POST
  • Headers: Content-Type:application/x-www-form-urlencoded
  • 本文: grant_type=client_credentials&client_id=@&client_secret=&resource=00000003-0000-0ff1-ce00-000000000000/.sharepoint.com@
  • セキュリティで保護された出力: チェックON

Lookupアクティビティ:取得したいフォルダ内のファイル一覧を取得する

まずはSPOのデータセットを作成します
ソースデータセットで新規を押してSharePoint Online リストを選択

image.png

データセットが作成されたら、リンクサービスで新規を押します
テスト接続が成功することを確認しておきます

  • テナント: アプリケーションのテナントID
  • サービスプリンシパルID: アプリケーションID
  • サービスプリンシパルキー: アプリケーションのクライアントシークレット

image.png

リンクサービスが作成できたら、リスト名でドキュメントを選択します

image.png

データのプレビューを押して、以下のようにドキュメント一覧が表示されたらOKです
私の環境では、名前という列にファイル名、パスという列に/sites/<site_name>/Shared Documents/General/...の形式でファイル名を除いたパスが表示されていました。このファイル名とパスを表す列名は後ほど使うのでコピーしておきましょう

image.png

やっとLookupアクティビティのソースデータセットが定義できました

次に、特定のフォルダ内のファイルのみコピーしたいので、クエリを使ってフィルターします
SharePoint REST APIには色んなクエリ操作が用意されていますが、今回は$filterクエリを利用します

パスが特定の文字列ではじまるという条件にします
startswithの1つめの引数が英語ではありませんが、シングルクォートなどは必要はありません

$filter=startswith(パス,'/sites/<site_name>/Shared Documents/General/...')

startswithのような関数は他にもあるので、他の条件を試したい場合はコチラを参考にしてください

これでもう一度プレビューしてみましょう
今度は対象フォルダのファイルだけが表示されていますね

Foreachアクティビティ:ファイル一覧をパラメーターにループ処理

ここまでで半分ぐらい終わりました
まずは、Foreachアクティビティの項目を指定します。ループ対象の配列を指定するイメージです
動的なコンテンツの追加をクリックして、@activity('Lookupアクティビティの名前').output.valueを入力しましょう
Lookupアクティビティの出力結果を確認したい場合は、Lookupアクティビティをデバッグ実行するとjson形式の出力が確認できます

image.png

出力サンプル
{
    "count": 3,
    "value": [
        {
            "コンテンツタイプのID": "xxxxx",
            "更新日時": "2020-10-21T11:59:55Z",
            "名前": "xxxxx",
            "コンプライアンス資産ID": null,
            "タイトル": null,
            "Tags": null,
            "ExtractedText": null,
            "場所国地域": null,
            "場所都道府県": null,
            "場所市区町村": null,
            "場所郵便番号コード": null,
            "場所番地": null,
            "場所座標": null,
            "場所名前": null,
            "ID": 24,
            "コンテンツタイプ": "ドキュメント",
            "登録日時": "2020-10-21T11:59:55Z",
            "登録者Id": 10,
            "更新者Id": 10,
            "コピー元": null,
            "承認の状況": "0",
            "パス": "xxxxx",
            "チェックアウト先Id": null,
            "ウイルスの状態": "2628",
            "現在のバージョン": true,
            "Owshiddenversion": 1,
            "バージョン": "1.0"
        },
        {
            "コンテンツタイプのID": "xxxxx",
            "更新日時": "2020-10-21T11:59:56Z",
            "名前": "xxxxx",
            "コンプライアンス資産ID": null,
            "タイトル": null,
            "Tags": null,
            "ExtractedText": null,
            "場所国地域": null,
            "場所都道府県": null,
            "場所市区町村": null,
            "場所郵便番号コード": null,
            "場所番地": null,
            "場所座標": null,
            "場所名前": null,
            "ID": 25,
            "コンテンツタイプ": "ドキュメント",
            "登録日時": "2020-10-21T11:59:56Z",
            "登録者Id": 10,
            "更新者Id": 10,
            "コピー元": null,
            "承認の状況": "0",
            "パス": "xxxxx",
            "チェックアウト先Id": null,
            "ウイルスの状態": "387602",
            "現在のバージョン": true,
            "Owshiddenversion": 1,
            "バージョン": "1.0"
        },
        {
            "コンテンツタイプのID": "xxxxx",
            "更新日時": "2020-10-21T11:59:56Z",
            "名前": "xxxxx",
            "コンプライアンス資産ID": null,
            "タイトル": null,
            "Tags": null,
            "ExtractedText": null,
            "場所国地域": null,
            "場所都道府県": null,
            "場所市区町村": null,
            "場所郵便番号コード": null,
            "場所番地": null,
            "場所座標": null,
            "場所名前": null,
            "ID": 26,
            "コンテンツタイプ": "ドキュメント",
            "登録日時": "2020-10-21T11:59:56Z",
            "登録者Id": 10,
            "更新者Id": 10,
            "コピー元": null,
            "承認の状況": "0",
            "パス": "xxxxx",
            "チェックアウト先Id": null,
            "ウイルスの状態": "2683952",
            "現在のバージョン": true,
            "Owshiddenversion": 1,
            "バージョン": "1.0"
        }
    ],
    "effectiveIntegrationRuntime": "DefaultIntegrationRuntime (Japan East)",
    "billingReference": {
        "activityType": "PipelineActivity",
        "billableDuration": [
            {
                "meterType": "AzureIR",
                "duration": 0.016666666666666666,
                "unit": "DIUHours"
            }
        ]
    },
    "durationInQueue": {
        "integrationRuntimeQueue": 1
    }
}

Foreach内のコピーアクティビティ(SharePointのAPIを利用してADLS Gen2にコピー)

ソースデータセットを定義します

image.png

リンクサービスの定義
ベースURLhttps://<tenant_name>.sharepoint.com/sites/<site_name>/_api/web/の形式**(末尾の"/"を忘れないようにしましょう)** 1

image.png

ここまで進めると、バイナリのデータセット定義が以下のようになっていると思います

image.png

ファイルのフルパスをパラメーターで指定したいので、パラメーターを追加します

image.png

そのパラメーターを使って相対URLを動的に指定します
image.png

相対URLの設定
GetFileByServerRelativeUrl('@{uriComponent(dataset().FilePath)}')/$value

GetFileByServerRelativeUrlはSharePoint REST APIのメソッドで相対URLを指定してファイルをダウンロードします。GetFileByServerRelativeUrlメソッドの引数に指定している@{uriComponent(dataset().FilePath)}の部分は、FilePathというパラメーターをData Factoryの関数uriComponentを使ってエンコードしています

Copyアクティビティの残りのソース定義を設定していきます
先程データセット定義で作成したFilePathというパラメーターがここに表示されています。Foreachでループ中の要素が持っているファイル名とファイルパスの情報を使ってファイルのフルパスを動的に指定します
動的なコンテンツの追加をクリックして、@{item().パス}/@{item().名前}と入力しましょう
ループ中の要素にアクセスする際はitem()を使います
item()の後ろには、SPOのデータをプレビューした時にコピーしたファイル名とパスを表す列名を使います

image.png

要求メソッド追加のヘッダーはドキュメント通りです

  • 要求メソッド: GET
  • 追加のヘッダー: @{concat('Authorization: Bearer ', activity('<Web-activity-name>').output.access_token)}

シンクデータセットを定義します

こちらはADLS Gen2のデータセット定義で特に注意すべきポイントもないので詳細は割愛します。SPOのファイル名をそのまま使いたいケースがほとんどかと思うので、ソースデータセットと同じように、FileNameのようなパラメーターを追加して、そのパラメーターに@item().名前を渡しておきましょう

image.png

さいごに

もっと簡単にできるのかと思っていましたが、思ったより苦戦しました…
他に良い方法があれば教えて下さいm(_ _)m

  1. 以下の説明を読むと、ベースURLと相対URLの間の"/"はData Factoryがつけてくれそうなもんですが、つけてくれなかったのでベースURLの末尾につけました
    image.png

3
1
2

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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?