はじめに
文中に出てくるMicrosoftのドキュメントを読めば何となく出来ると思いますが、若干躓いたのでメモします。
準備
Microsoft Graph Java SDK
今回はMicrosoft Graph Java SDKを使います。手順はMicrosoftのページに記載されています。
Microsoft Graph Java SDK をインストールする
クライアントID/クライアントシークレット生成(AzureAD)
この手順も既に色々な方が手順を記載しています。最近だと↓の記事が新しいでしょうか。
次世代のコラボレーション!Microsoft TeamsにChatGPTを組み込む方法
アクセス権は「file.readwrite.all」「sites.ReadWrite.all」が必要のようです。詳細はMicrosoftのページに記載されています。
DriveItem の内容をアップロードまたは置換する
https://learn.microsoft.com/ja-jp/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=http
siteidの取得
ファイルをアップロードしたいサイトを一意に示すIDがsiteidのようです。siteidはSharePoint管理センターとかで、URLに表示されますが、Graph Explorerを使って取得することができます。
Graph Explorerにブラウザでアクセスしてログインします。
https://developer.microsoft.com/en-us/graph/graph-explorer
以下のURLをGETでリクエストします。
https://graph.microsoft.com/v1.0/sites/<hostname>.sharepoint.com:/sites/<sitename>
サイトのURLが以下の場合は、
https://XXXXX.sharepoint.com/sites/YYYYY
リクエストするURLは以下になります。
https://graph.microsoft.com/v1.0/sites/XXXXX.sharepoint.com:/sites/YYYYY
以下のJSONがレスポンスされます。
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites/$entity",
"createdDateTime": "2017-11-10T00:57:10.92Z",
"description": "*****",
"id": "*****.sharepoint.com,16bc4df0-7e1a-4cec-9ade-86f56a8e9b6e,320ed486-518c-4495-8997-1af19888f3c6",
"lastModifiedDateTime": "2023-05-02T08:38:46Z",
"name": "zangyo",
"webUrl": "https://*****.sharepoint.com/sites/*****",
"displayName": "*****",
"root": {},
"siteCollection": {
"hostname": "*****.sharepoint.com"
}
}
上から5行目のIDにsiteidが含まれています。
"id": "*****.sharepoint.com,16bc4df0-7e1a-4cec-9ade-******,320ed486-518c-4495-8997-1a*****",
カンマ区切りの2つ目の「16bc〜」がsiteidになります。
実装
SDKにはファイルサイズが小さい用と大きい用の2つが用意されています。何をもって小さい大きいのかよく分からなかったです。
ファイルサイズが小さい場合
Microsoftのドキュメントにサンプルが載っていますが、サンプルでは自分のOneDriveにアップロードする場合なので、SharePointでは若干変更が必要です。
DriveItem の内容をアップロードまたは置換する
https://learn.microsoft.com/ja-jp/graph/api/driveitem-put-content?view=graph-rest-1.0&tabs=java
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.requests.GraphServiceClient;
public class SharePointUploadTest {
public static void main(String[] args) throws IOException {
final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId("<クライアントID>")
.clientSecret("<クライアントシークレット>")
.tenantId("<テナントID>")
.build();
final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(clientSecretCredential);
GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( tokenCredentialAuthProvider ).buildClient();
FileInputStream inputStream = new FileInputStream("<アップロードするファイルパス>");
byte[] stream = IOUtils.toByteArray(inputStream);
String siteid = "<siteid>";
graphClient.sites().byId(siteid).drive().root().itemWithPath("<アップロード先フォルダ&ファイル名>").content().buildRequest().put(stream);
}
}
サイトの「Shared Documents」がルートになるようなので、以降のパスを指定します。
「/hoge/hoge1.png」この場合は「Shared Documents/hoge/hoge1.png」にアップロードされます。
- 指定されたフォルダが存在しない場合は自動で作成される。
- 同名ファイルが存在した場合は上書き
このサンプルソースで130MBのファイルをアップロードしたところ正常終了しました。Javaヒープサイズ次第なような気がしますが。
ファイルサイズが大きい場合
再開可能なAPI(UploadSession)が用意されており、ファイルサイズが大きい場合はこちらを使用します。Javaの場合は再開機能はサポートされていないようです。
UploadSessionを使うと、チャンクな感じでアップロードすることができます。
driveItem: createUploadSession
https://learn.microsoft.com/ja-jp/graph/api/driveitem-createuploadsession?view=graph-rest-1.0&preserve-view=true
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.DriveItem;
import com.microsoft.graph.models.DriveItemCreateUploadSessionParameterSet;
import com.microsoft.graph.models.DriveItemUploadableProperties;
import com.microsoft.graph.models.UploadSession;
import com.microsoft.graph.requests.GraphServiceClient;
import com.microsoft.graph.tasks.IProgressCallback;
import com.microsoft.graph.tasks.LargeFileUploadTask;
public class SharePointUploadTest2 {
public static void main(String[] args) throws IOException {
final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
.clientId("<クライアントID>")
.clientSecret("<クライアントシークレット>")
.tenantId("<テナントID>")
.build();
final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(clientSecretCredential);
GraphServiceClient graphClient = GraphServiceClient.builder().authenticationProvider( tokenCredentialAuthProvider ).buildClient();
File file = new File("<アップロードするファイルパス>");
FileInputStream inputStream = new FileInputStream(file);
IProgressCallback callback = new IProgressCallback() {
@Override
public void progress(final long current, final long max) {
System.out.println(
String.format("Uploaded %d bytes of %d total bytes", current, max)
);
}
};
DriveItemCreateUploadSessionParameterSet uploadParams =
DriveItemCreateUploadSessionParameterSet.newBuilder()
.withItem(new DriveItemUploadableProperties()).build();
UploadSession uploadSession = graphClient.sites().byId("<siteid>").drive().root()
.itemWithPath("<アップロード先フォルダ&ファイル名>")
.createUploadSession(uploadParams)
.buildRequest().post();
LargeFileUploadTask<DriveItem> largeFileUploadTask =
new LargeFileUploadTask<DriveItem>
(uploadSession, graphClient, inputStream, file.length(), DriveItem.class);
largeFileUploadTask.upload(0, null, callback);
}
}
Microsoftのサンプルをサイト指定にしただけで、あとは殆ど変更していません。
終わりに
サンプルを見ればすぐ出来ますが、今回はsiteidの取得の仕方で大分悩みました。