アプリ開発備忘録

PlayStationMobile、Android、UWPの開発備忘録

SharePointにAPIを使用してファイルをアップロードする

言語はKotlin(Java17)を使用しました。

アプリの登録

adminではないユーザーを使用しました。新規登録からアプリを登録します。
https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade

「この組織ディレクトリのみに含まれるアカウント」のシングルテナントで十分なのでこちらを選択します。

ここに表示されている「アプリケーション (クライアント) ID」と「ディレクトリ (テナント) ID」は後で使用します。
クライアントの資格情報を開きます。「新しいクライアントシークレット」からシークレットを追加します。

値の方のクライアントシークレットをメモします。今しか見れないので注意。

権限の追加

APIのアクセス許可から「アクセス許可の追加」を選択します。

Microsoft Graphを選択します。

アプリケーションの許可を選びます。

FIles.ReadWrite.All を選択します。

管理者の同意が必要と出るので管理アカウントに切り替えます。

許可します。

アプリケーションコード

依存。 kotlin.gradle.kts

plugins {
    id("java")
    kotlin("jvm") version "1.8.10"
    kotlin("plugin.serialization") version "1.8.10"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib"))
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
}

Tokenの取得

型を用意するまでも無いのでJsonObjectでパースしています。
上記で取得した tenantId, clientId, clientSecret を使用してBearerTokenを取得します。

private fun getBearerToken(
    tenantId: String,
    clientId: String,
    clientSecret: String,
): String {
    val result = HttpClient.newHttpClient()
        .send(
            HttpRequest.newBuilder(URI("https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"))
                .header("Content-Type", "application/x-www-form-urlencoded")
                .method(
                    "POST", HttpRequest.BodyPublishers.ofString(
                        createFormParam(
                            "client_id" to clientId,
                            "scope" to "https://graph.microsoft.com/.default",
                            "client_secret" to clientSecret,
                            "grant_type" to "client_credentials",
                        )
                    )
                )
                .build(),
            HttpResponse.BodyHandlers.ofString()
        )
    val response = result.body()
    println(result.statusCode())
    println(response)

    return Json.decodeFromString<JsonObject>(response)
        .getValue("access_token")
        .jsonPrimitive
        .content
}

private fun createFormParam(vararg keyValue: Pair<String, String>): String {
    return keyValue.map {
        URLEncoder.encode(it.first, Charsets.UTF_8) to
            URLEncoder.encode(it.second, Charsets.UTF_8)
    }.joinToString("&") { "${it.first}=${it.second}" }
}

アップロード

4MBまでのファイルをアップロードします。
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_put_content?source=recommendations&view=odsp-graph-online

大きいファイルをアップロードしたい場合はこちらを参考に。
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/concepts/upload?view=odsp-graph-online

userObjectId は「所有者」からユーザーを選択し、「オブジェクト ID」から見れます。

とりあえずテキストファイル決め打ちになっています。

private fun upload(
    filePath: String,
    bearerToken: String,
    inputStream: InputStream,
    userObjectId: String,
) {
    val url = "https://graph.microsoft.com/v1.0/users/$userObjectId/drive/root:$filePath:/content"

    val result = HttpClient.newHttpClient()
        .send(
            HttpRequest.newBuilder(URI(url))
                .header("Authorization", "Bearer $bearerToken")
                .header("Content-Type", "text/plain")
                .method(
                    "PUT", HttpRequest.BodyPublishers.ofInputStream {
                        inputStream
                    }
                )
                .build(),
            HttpResponse.BodyHandlers.ofString()
        )

    println(result.statusCode())
    println(result.body())
}

おわりに

この記事は以下のGraph Explorerを使用して試行錯誤しながら書きました。
https://developer.microsoft.com/ja-jp/graph/graph-explorer