Boxはクラウドにファイルを保存できるサービスです。Box は API を用意しており、これを介してファイルやフォルダを操作できます。またこの API をプログラム上から楽に操作するための SDK が用意されています。
Box — セキュアなクラウドコンテンツ管理、ワークフロー、コラボレーション
APIリファレンス – Box Developerドキュメント
.NET SDKのインストール – Box Developerドキュメント
この API を利用してファイルやフォルダを移動できるのですが、移動時にああしたいこうしたいといった処理は Box 側では用意されていません。常に上書き禁止のみです。もしそういった処理をしたいのであれば自前で用意する必要があります。この処理の作り方を紹介します。例のコードはいずれもファイルの移動ですが、フォルダも同様にできます。
C#のSDKを使ってファイルを移動するのみなら次のコードでできます。これは Box API のデフォルトの挙動がそのまま反映されます。
var request = new BoxFileRequest() { Id = "ファイルID", Parent = new BoxRequestEntity() { Id = "移動先フォルダID" } }; BoxFile response = await client.FilesManager.UpdateInformationAsync(request);
これは Box API のファイルを更新する API を実行しています。親フォルダのIDを付け替えることでフォルダ間を移動します。ファイルIDとフォルダIDはあらかじめフォルダ内の項目のリストを取得などのAPIで取得しておきます。
ファイルを更新 – APIリファレンス – Box Developerドキュメント#parent
object本文内ファイルの新しい親フォルダ (省略可)。これを使用して、ファイルを新しいフォルダに移動できます。
string本文内省略可能"123"
親項目のID
このままだと次の様に同名ファイルが存在した場合エラーになります。これはBox APIによって定められた挙動です。同名ファイルが存在した場合、上書きしないだけでいいのならばこれでもいいのですが、そうでない場合も多々あります。例えば上書きしたい場合があります。これは次でできます。
// 移動先のフォルダ内の項目リストを取得 var itemsInDestFolder = await client.FoldersManager.GetFolderItemsAsync(distFolder.Id, limit: 100); // 同名ファイルが存在する場合、あらかじめそれを削除 var alreadyExistingItem = itemsInDestFolder.Entries.Find(existingItem => existingItem.Name == item.Name); if (alreadyExistingItem != null) { await client.FilesManager.DeleteAsync(alreadyExistingItem.Id); } // 先述と同様の移動処理 var request = new BoxFileRequest() { Id = "ファイルID", Parent = new BoxRequestEntity() { Id = "移動先フォルダID" }, }; BoxFile response = await client.FilesManager.UpdateInformationAsync(request);
既存ファイルを削除してから移動します。注意点としてBoxとしてファイルを削除している点があります。このためBoxのファイルバージョン管理機能が期待通りに動作しないやもしれません。ファイルバージョンについてですが、並列させようにも新旧のファイルバージョンをどう混ぜるのかちょっといい感じの案が思い浮かびませんが、もしかしたら次のファイルバージョンAPIで何か目的にあった別のものが作れるやもしれません。
ファイルバージョンをアップロード – APIリファレンス – Box Developerドキュメント
すべてのファイルバージョンのリストを取得 – APIリファレンス – Box Developerドキュメント
別名ファイルにする方法もあります。これは次の様にできます。
// 移動先のフォルダ内の項目リストを取得 var itemsInDestFolder = await client.FoldersManager.GetFolderItemsAsync(distFolder.Id, limit: 100); // 同名ファイルが存在する場合、新しいファイル名を作成 string newFileName = item.Name; if (itemsInDestFolder.Entries.Any(existingItem => existingItem.Name == item.Name)) { // とりあえず日時を追加した名前作成 newFileName = $"{Path.GetFileNameWithoutExtension(item.Name)}-{DateTime.Now.ToString("yyyyMMdd_HHmmss")}{Path.GetExtension(item.Name)}"; } // 日時の追加でも被った場合、ランダム文字列を追加 if (itemsInDestFolder.Entries.Any(existingItem => existingItem.Name == newFileName)) { var randomizer = new Random(); string randomString = string.Concat(Enumerable.Range(0, 6).Select(i => char.ConvertFromUtf32(randomizer.Next('a', 'z' + 1)))); newFileName = $"{Path.GetFileNameWithoutExtension(newFileName)}-{randomString}{Path.GetExtension(newFileName)}"; } // 先述と同様の移動処理に名前の変更を追加 var request = new BoxFileRequest() { Id = "ファイルID", Parent = new BoxRequestEntity() { Id = "移動先フォルダID" }, Name = newFileName, }; BoxFile response = await client.FilesManager.UpdateInformationAsync(request);
移動先のフォルダの中身を調べて同名が既にいたら別名を作り、それを込みで更新します。注意点として別名自体が被るパターンがあることです。上記例も秒まで被った上にランダム6文字が被ることはないだろう、という仮定の元に作られています。とはいえBoxは同名の何かを保存しようとした場合、元々あるものを壊さずにエラーになってくれるので安心安全です。プログラム上で問題が起きてもやり直せます。