1. システムとオフィスの融合
  2. media
  3. Teams Azure
  4. Teams データを取得してみた(3)

QESブログ

Teams データを取得してみた(3)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
本シリーズの構成は、以下になります。
第1回 Teams データを取得してみた(1) Teams API利用のための基本設定やプログラム(C#)からのチャネルメッセージの取得等を試しています。
第2回 Teams データを取得してみた(2) チャネルメッセージ、リプライメッセージやリアクション情報の取得や解析を試しています。
第3回 Teams データを取得してみた(3) Teamsに登録されたファイルの一覧の取得を試しています。

番外編 Power Platform で Teams データを取得してみた Power Platformでデータ取得を試しています。

前回までは、投稿データの取得やリアクションデータの判定を試してみました。

Teamsを使い続けていくと、アクティブなチーム/チャネルも多数ありますが、もう使わなくなったチーム/チャネルも多数出てきます。
似たようなチャネルも多かったり、どこかにアップロードしたファイルが行方不明になることもよくあると思います。

今回は、迷子になったファイルを探すために、Teams APIを使ってみたいと思います。

ファイルの所在を確認する

Teamsにアップロードされたファイルは、SharePoint Onlineに格納されます。
そのファイルがどこにあるか、Teams APIで探してみます。

ファイルの保存されている場所は、チャネルの [filesFolder] APIで確認できます。(⇒filesFolderを取得する)
GET /teams/{id}/channels/{id}/filesFolder

取得対象のチャネルは、こちら。
TeamsAPI3-001.png
チームのIDとチャネルのIDを使った問い合わせは、過去の回で実施していますので、同様に Graph Explorer を使って呼び出してみます。
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#teams('a31fdde2-fec2-4cd3-b720-f9ce6f28746f')/channels('19%3A9Y-zafBu3W_jmU0YwighDGyOtqiSqq-7hBXr7QXFnL41%40thread.tacv2')/filesFolder/$entity",
    "id": "01TC7XEOACTQJURA53TNE3XUKASZ7EG7XX",
    "createdDateTime": "0001-01-01T00:00:00Z",
    "lastModifiedDateTime": "2022-07-23T09:36:22Z",
    "name": "General",
    "webUrl": "https://-----.sharepoint.com/sites/Public_Taro/Shared%20Documents/General",
    "size": 67243,
    "parentReference": {
        "driveId": "b!2uMtA2-iD0mb_XU2UGoeHp5PRgY8vc5OstCbvdGmHTymrVrxLEfDRoUiLwElSiFV",
        "driveType": "documentLibrary"
    },
    "fileSystemInfo": {
        "createdDateTime": "2022-07-23T09:36:22Z",
        "lastModifiedDateTime": "2022-07-23T09:36:22Z"
    },
    "folder": {
        "childCount": 2
    }
}
このチャネルのファイル置き場情報を取得できました。
取得結果に、[webUrl] という項目がありますが、このURLをブラウザに入力すると、SharePoint Onlineのファイルのある場所を直接表示することができます。
TeamsAPI3-003.png
Teamsで表示されていたものと同じフォルダの情報が取得できていることが分かります。

ファイルの情報を取得する

ルートとなるフォルダの情報は取得できました。引き続き格納されているファイル情報も取得していきます。
(※この先は、Teams API というわけでも無く、タイトルから外れていく気がしますが、気にしないで進めます。)

ファイル情報等は、DriveItemというリソース情報を保持しています。(⇒DriveItem リソースを取得する

チャネルのファイル保存場所の取得結果で、[driveId]がありましたので、以下が使えそうです。
{item-id}には、filesFolderで取得したオブジェクトのIDを指定します。
GET /drives/{drive-id}/items/{item-id}

取得したID情報で、DriveItem情報を取得してみます。
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#drives('b%212uMtA2-iD0mb_XU2UGoeHp5PRgY8vc5OstCbvdGmHTymrVrxLEfDRoUiLwElSiXX')/items/$entity",
    "createdDateTime": "2022-07-23T09:36:22Z",
    "eTag": "\"{48139C02-BB83-499B-BBD1-40967E437FAD},2\"",
    "id": "01TC7XEOACTQJURA53TNE3XUKASZ7EG7XX",
    "lastModifiedDateTime": "2022-07-23T09:36:22Z",
    "name": "General",
    "webUrl": "https://-----.sharepoint.com/sites/Public_Taro/Shared%20Documents/General",
    "cTag": "\"c:{48139C02-BB83-499B-BBD1-40967E437FAD},0\"",
    "size": 67243,
    "createdBy": {
        "application": {
            "id": "cc15fd57-2c6c-4117-a88c-83b1d56b4bbe",
            "displayName": "Microsoft Teams Services"
        },
        "user": {
            "email": "test.taro@-----.onmicrosoft.com",
            "id": "0d00906a-f129-429a-9ab8-4b82b3da253d",
            "displayName": "テスト 太郎"
        }
    },
    "lastModifiedBy": {
        "application": {
            "id": "cc15fd57-2c6c-4117-a88c-83b1d56b4bbe",
            "displayName": "Microsoft Teams Services"
        },
        "user": {
            "email": "test.taro@-----.onmicrosoft.com",
            "id": "0d00906a-f129-429a-9ab8-4b82b3da253d",
            "displayName": "テスト 太郎"
        }
    },
    "parentReference": {
        "driveType": "documentLibrary",
        "driveId": "b!2uMtA2-iD0mb_XU2UGoeHp5PRgY8vc5OstCbvdGmHTymrVrxLEfDRoUiLwElSiXX",
        "id": "01TC7XEOF6Y2GOVW7725BZO354PWSELRRZ",
        "path": "/drives/b!2uMtA2-iD0mb_XU2UGoeHp5PRgY8vc5OstCbvdGmHTymrVrxLEfDRoUiLwElSiXX/root:"
    },
    "fileSystemInfo": {
        "createdDateTime": "2022-07-23T09:36:22Z",
        "lastModifiedDateTime": "2022-07-23T09:36:22Z"
    },
    "folder": {
        "childCount": 2
    }
}
対象IDが同じなので、filesFolderで取得したものと同じデータのようですが、取得できる項目が増えているようです。
子要素(childCount)があることを確認できますので、階層情報を含めてファイルを取得してみます。
フォルダの子要素を取得するには、そのオブジェクトの[children] で取得できます。
(⇒driveItem の子を一覧表示する
GET /drives/{drive-id}/items/{item-id}/children

プログラムからファイル情報を取得する

階層情報やファイル数が増えてくると、手動でGraph Explorerから取得するのは大変なので、プログラムでファイル情報を取得します。

参加しているチームのチャネルに存在するファイルを一通り取得するプログラムを作ります。
ちなみに Public_Taro の 一般チャネルのフォルダ構成は、このようになっています。

TeamsAPI3-002.png
ファイル情報取得用のサンプルコードは、以下になります。
(※取得部分の抜粋となります。接続部分等は、過去回等をご参照ください。)
// ファイル情報を取得
var teams = await graphClient.Me.JoinedTeams.Request().GetAsync();
foreach (var team in teams)
{
    Console.WriteLine($"チーム名:{team.DisplayName}");

    // チャネル一覧の取得
    var channels = await graphClient.Teams[team.Id].Channels.Request().GetAsync();
    foreach (var channel in channels)
    {
        Console.WriteLine($"チャネル名:{channel.DisplayName}");

        // 格納先情報の取得
        var filesFolder = await graphClient.Teams[team.Id].Channels[channel.Id].FilesFolder.Request().GetAsync();

        // アイテム情報の取得
        var item = await graphClient.Drives[filesFolder.ParentReference.DriveId].Items[filesFolder.Id].Request().GetAsync();

        // 子アイテムの取得
        int depth = 1;
        await ChildItem(filesFolder.ParentReference.DriveId, item, depth);

        Console.WriteLine("");
    }
}

async Task ChildItem(string driveId, DriveItem item, int depth)
{
    Console.Write(new string(' ', depth));
    Console.WriteLine($"+{item.Name}");

    var subItems = await graphClient.Drives[driveId].Items[item.Id].Children.Request().GetAsync();
    if (subItems.Count > 0)
    {
        foreach (var subItem in subItems)
        {
            await ChildItem(driveId, subItem, depth + 1);
        }
    }
    else
    {
        return;
    }
}
取得できました♪
参加している全てのチームのチャネルを参照しているため、Public_Taro チーム以外の情報も取得できましたが、画面から見たファイルと同じものが取れていることが確認できます。
TeamsAPI3-004.png

ファイル名のみでは無く、WebUrlなども一緒に取得しておくと、直接SharePointサイトにアクセスする際に便利です。
例えば、こんな感じで。(ファイル名とwebUrlをカンマ区切りで出力しているだけですが)
General,https://-----.sharepoint.com/sites/Public_Taro/Shared%20Documents/General
TestFolder,https://-----.sharepoint.com/sites/Public_Taro/Shared%20Documents/General/TestFolder
連絡用,https://-----.sharepoint.com/sites/Public_Taro/Shared%20Documents/General/TestFolder/%E9%80%A3%E7%B5%A1%E7%94%A8
aaa.docx,https://-----.sharepoint.com/sites/Public_Taro/_layouts/15/Doc.aspx?sourcedoc=%7BDDC7533C-B0AE-420E-9A71-34971E400382%7D&file=aaa.docx&action=default&mobileredirect=true
bbb.docx,https://-----.sharepoint.com/sites/Public_Taro/_layouts/15/Doc.aspx?sourcedoc=%7B968B2A9A-85D1-44DA-BD7B-0CC3D1545AA6%7D&file=bbb.docx&action=default&mobileredirect=true
テスト文書.docx,https://-----.sharepoint.com/sites/Public_Taro/_layouts/15/Doc.aspx?sourcedoc=%7B3055200E-6F2A-4E82-9EDF-ECA7E7F84B07%7D&file=%E3%83%86%E3%82%B9%E3%83%88%E6%96%87%E6%9B%B8.docx&action=default&mobileredirect=true
book1.xlsx,https://-----.sharepoint.com/sites/Public_Taro/_layouts/15/Doc.aspx?sourcedoc=%7B92918B5B-A862-40CC-8AF5-AA4FAB746ED9%7D&file=book1.xlsx&action=default&mobileredirect=true

このあたりの情報を見れば、迷子になったファイルの場所が分かるかもしれません。
(迷子になったファイル名を覚えていれば、、、ですが、、)

他にもファイルサイズ等の必要な情報を追加したり、画面に表示してみたり、データベースに格納するなどいろいろ活用できそうです。

最後に

実際の運用環境で使用する場合は、日々ファイルの増減がありますし、膨大なファイル数になるかと思いますので
全てを毎回取得するのは現実的では無いかもしれません。
迷子ファイル探しという理由だけで、毎回全ファイルの一覧を取得するというのは、やり過ぎかもしれません。
適当なチームやチャネルに絞って取得する方が現実的でしょう。

今回取得したdriveItemリソース情報は、ファイル名やサイズだけでなく、アクセス権の設定情報も取得できます(⇒permissions)。
アクセス権を確認すると、誰にどのような権限が付与されているか分かります。リンクを知っていれば誰でも開ける共有方法もあるため、予期せず外部共有されているファイルを見つけることができるかもしれません。
また、ファイル名から推測して、社内ルールなどで本来アップロードしてはいけないような機密情報のファイルを見つけることができるかもしれません。

QESでは様々なアプリケーションの開発・導入を行っております。
私共が提供するサービス・ソリューションにつきましてはこちらに掲載しております。

システム開発・構築でお困りの問題や弊社が提供するサービス・ソリューションにご興味を抱かれましたら、是非一度お問い合わせください。

QESではクラウドエンジニアを募集しております。

※このブログで参照されている、Microsoft、Windows、Azure、Teamsその他のマイクロソフト製品およびサービスは、米国およびその他の国におけるマイクロソフトの商標または登録商標です。
  • LINEで送る
  • このエントリーをはてなブックマークに追加

お気軽にお問い合わせください。

ページのトップへ