Microsoft 365 OneDrive for Business: ファイル / フォルダ検索

Overview

Basic Configs
工程名
メモ
Auto Step icon
Configs for this Auto Step
conf_OAuth2
C1: OAuth2 設定 *
conf_ParentFolderUrl
C2: 検索対象の親フォルダの URL(空白の場合、ルートフォルダ直下を検索します)
conf_Name
C3: 検索する名前(大文字・小文字は区別されません) *#{EL}
conf_Status
C4: 検索結果のステータスを保存するデータ項目
conf_FoundUrl
C5: 見つかった項目の URL を保存するデータ項目

Notes

  • Microsoft 365 の OneDrive for Business で使用できる自動工程です
    • 個人用の OneDrive では使用できません
  • フォルダの URL は、OneDrive でフォルダの「詳細」メニューを開き、「パス」の隣のコピーアイコンから取得できます
    • 上部メニューの「共有」や「リンクのコピー」から取得した URL も使用できます

See Also

Script (click to open)
  • 次のスクリプトが記述されている XML ファイルをダウンロードできます
    • onedrive-file-search.xml (C) Questetra, Inc. (MIT License)
    • Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます

// OAuth2 config sample at [OAuth 2.0 Setting]
// - Authorization Endpoint URL: https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize
// - Token Endpoint URL: https://login.microsoftonline.com/organizations/oauth2/v2.0/token
// - Scope: Files.ReadWrite.All offline_access
// - Consumer Key: (Get by Microsoft Entra ID)
// - Consumer Secret: (Get by Microsoft Entra ID)

const GRAPH_URI = "https://graph.microsoft.com/v1.0/";

const main = () => {
    //// == 工程コンフィグの参照 / Config Retrieving ==
    const oauth2 = configs.getObject('conf_OAuth2');
    const parentFolderUrl = retrieveParentFolderUrl();
    const name = configs.get('conf_Name');
    if (name === '' || name === null) {
        throw new Error('Name to search for is blank.');
    }
    const statusDef = configs.getObject('conf_Status');
    const foundUrlDef = configs.getObject('conf_FoundUrl');
    if (statusDef === null && foundUrlDef === null) {
        throw new Error('Neither of the data items to save the result is set.');
    }

    //// == 演算 / Calculating ==
    const parentFolderInfo = getFolderInfoByUrl(oauth2, parentFolderUrl);
    const {foundUrl, status} = search(oauth2, parentFolderInfo, name);

    //// == ワークフローデータへの代入 / Data Updating ==
    saveData(statusDef, status);
    saveData(foundUrlDef, foundUrl);
};

/**
 * config から親フォルダの URL を読み出す
 * @returns {String}
 */
const retrieveParentFolderUrl = () => {
    const confName = 'conf_ParentFolderUrl';
    const folderUrlDef = configs.getObject(confName);
    let folderUrl = configs.get(confName);
    if (folderUrlDef !== null) {
        folderUrl = engine.findData(folderUrlDef);
    }
    return folderUrl;
};

/**
  * フォルダの URL からドライブアイテムのメタデータを取得し、
  * オブジェクトで返す(URL が空の場合はドライブ ID を me/drive、フォルダ ID を root にする)
  * @param {AuthSettingWrapper} oauth2 OAuth2 認証設定
  * @param {String} folderUrl フォルダの URL
  * @return {Object} folderInfo フォルダの情報 {driveId, folderId}
  */
const getFolderInfoByUrl = (oauth2, folderUrl) => {
    let folderInfo = { driveId: 'me/drive', folderId: 'root' };
    if (folderUrl !== '' && folderUrl !== null) {
        // 分割代入
        const {
            id,
            folder,
            parentReference: {
                driveId
            }
        } = getObjBySharingUrl(oauth2, folderUrl);
        if (folder === undefined || folder === null) {
            throw new Error('The drive item specified by Parent Folder URL is not a folder.');
        }
        folderInfo = { driveId: `drives/${driveId}`, folderId: id };
    }
    return folderInfo;
};

/**
  * OneDrive のドライブアイテム(ファイル、フォルダ)のメタデータを取得し、JSONオブジェクトを返す
  * APIの仕様:https://learn.microsoft.com/ja-jp/graph/api/shares-get?view=graph-rest-1.0&tabs=http
  * @param {AuthSettingWrapper} oauth2 OAuth2 認証設定
  * @param {String} sharingUrl ドライブアイテムの共有 URL
  * @return {Object} responseObj ドライブアイテムのメタデータの JSON オブジェクト
  */
const getObjBySharingUrl = (oauth2, sharingUrl) => {
    const encodedSharingUrl = encodeSharingUrl(sharingUrl);
    const response = httpClient.begin()
        .authSetting(oauth2)
        .get(`${GRAPH_URI}shares/${encodedSharingUrl}/driveItem`);
    const httpStatus = response.getStatusCode();
    const responseStr = response.getResponseAsString();
    if (httpStatus !== 200) {
        engine.log(responseStr);
        throw new Error(`Failed to get drive item. status: ${httpStatus}`);
    }
    return JSON.parse(responseStr);
};

/**
  * 共有URLを unpadded base64url 形式にエンコードする
  * @param {String} sharingUrl  共有URL
  * @returns {String} encodedSharingUrl  エンコードされた共有URL
  */
const encodeSharingUrl = (sharingUrl) => {
    let encodedSharingUrl = base64.encodeToUrlSafeString(sharingUrl);
    while (encodedSharingUrl.slice(-1) === '=') {
        encodedSharingUrl = encodedSharingUrl.slice(0, -1);
    }
    return `u!${encodedSharingUrl}`;
};

const STATUS_FOUND_FOLDER = 'FOUND_FOLDER';
const STATUS_FOUND_FILE = 'FOUND_FILE';
const STATUS_FOUND_OTHER = 'FOUND_OTHER';
const STATUS_NOT_FOUND = 'NOT_FOUND';

/**
  * 検索する
  * 親フォルダ直下の子アイテムを "@odata.nextLink" が無くなるまで(または HTTP リクエスト数の上限に達するまで)ページングしながら走査し、
  * 名前が一致するドライブアイテムを探す
  * @param {AuthSettingWrapper} oauth2 OAuth2 認証設定
  * @param {Object} parentFolderInfo 親フォルダの情報 {driveId, folderId}
  * @param {String} name 検索する名前
  * @return {Object} result 検索結果 {status, foundUrl}
  */
const search = (oauth2, parentFolderInfo, name) => {
    const { driveId, folderId } = parentFolderInfo;
    let url = `${GRAPH_URI}${driveId}/items/${folderId}/children`;
    let isFirstRequest = true;
    const limit = httpClient.getRequestingLimit();
    for (let count = 0; count < limit; count++) {
        let request = httpClient.begin().authSetting(oauth2)
            .header('Prefer', 'Include-Feature=AddToOneDrive'); // ショートカットを含めるために必要
        if (isFirstRequest) {
            // 2 回目以降は @odata.nextLink に必要なクエリが含まれているため、$select は初回のみ付与する
            request = request.queryParam('$select', 'name,file,folder,webUrl');
        }
        isFirstRequest = false;

        const response = request.get(url);
        const status = response.getStatusCode();
        const responseStr = response.getResponseAsString();
        if (status !== 200) {
            engine.log(responseStr);
            throw new Error(`Failed to search. status: ${status}`);
        }

        const json = JSON.parse(responseStr);
        const items = json.value || [];
        const foundItem = items.find((item) => item.name.toLowerCase() === name.toLowerCase());
        if (foundItem !== undefined) {
            const webUrl = foundItem.webUrl;
            return {
                status: classify(foundItem),
                foundUrl: (webUrl === undefined || webUrl === '') ? null : webUrl
            };
        }

        const nextLink = json['@odata.nextLink'];
        if (nextLink === undefined || nextLink === null || nextLink === '') {
            // 最終ページまで走査して見つからなかった場合は、正常な検索結果として NOT_FOUND を返す
            return { status: STATUS_NOT_FOUND, foundUrl: null };
        }
        url = nextLink;
    }
    throw new Error('Too many drive items are in the specified folder. The search could not be completed.');
};

/**
  * ドライブアイテムの facet(folder / file の有無)から検索結果ステータスを判定する
  * @param {Object} item 名前が一致したドライブアイテム
  * @return {String} 検索結果ステータス
  */
const classify = (item) => {
    if (item.folder !== undefined && item.folder !== null) {
        return STATUS_FOUND_FOLDER;
    }
    if (item.file !== undefined && item.file !== null) {
        return STATUS_FOUND_FILE;
    }
    return STATUS_FOUND_OTHER;
};

/**
 * データ項目への保存
 * @param {ProcessDataDefinitionView} def
 * @param {*} data
 */
const saveData = (def, data) => {
    if (def === null) {
        return;
    }
    engine.setData(def, data);
};

    

Questetra Supportをもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む