ドライブアップロード
Misskey のドライブはファイルストレージ機能です。ノートに添付するファイルは、すべて事前にドライブへアップロードする必要があります。client.drive ファサードは files、folders、stats のサブ API を公開しています。
すべてのファイルの取得、一括移動、一括アップロード、フォルダの再帰的な削除など、複数のリクエストを組み合わせる操作についてはドライブヘルパーも参照してください。
ファイルのアップロード
import 'dart:io';
final bytes = await File('photo.jpg').readAsBytes();
final driveFile = await client.drive.files.create(
bytes: bytes,
filename: 'photo.jpg',
comment: 'Alt text for accessibility',
);
print(driveFile.id); // ノートへの添付に使用する ID
print(driveFile.url); // 公開 URL
フォルダとセンシティブ指定を伴うアップロード
final driveFile = await client.drive.files.create(
bytes: bytes,
filename: 'nsfw.jpg',
folderId: myFolderId,
isSensitive: true,
force: true, // 同じ内容のファイルがすでに存在してもアップロードする
);
Misskey はアップロードを名前ではなく内容(MD5 ハッシュ)で重複排除します。force を指定しない場合、ドライブにすでに存在する内容をアップロードすると既存のファイルが返され、指定した folderId、name、comment は無視されます。バイト列の転送自体を避けたい場合は、ドライブヘルパーの createDeduplicated() を参照してください。
アップロードの進捗
final driveFile = await client.drive.files.create(
bytes: largeBytes,
filename: 'large-video.mp4',
onSendProgress: (sent, total) {
final percent = (sent / total * 100).toStringAsFixed(1);
print('Uploading: $percent%');
},
);
URL からのアップロード
await client.drive.files.uploadFromUrl(
url: 'https://example.com/image.jpg',
folderId: myFolderId,
isSensitive: false,
);
このエンドポイントは完了を待たずに戻り、ファイルは非同期でドライブに追加されます。force の意味は create() と同じです。作成されたファイルを待つには uploadFromUrlAndWait() を使用してください。
ドライブのファイルをノートに添付する
final driveFile = await client.drive.files.create(
bytes: imageBytes,
filename: 'photo.jpg',
);
final note = await client.notes.create(
text: 'Check this out!',
fileIds: [driveFile.id],
);
fileIds に複数の ID を渡すと、複数のファイルを添付できます。
ファイル一覧の取得
// ルートフォルダのファイル一覧
final files = await client.drive.files.list(limit: 20);
// 特定のフォルダのファイル一覧
final files = await client.drive.files.list(
limit: 20,
folderId: myFolderId,
);
// MIME タイプで絞り込む
final images = await client.drive.files.list(type: 'image/*');
// サイズの降順でソート
final large = await client.drive.files.list(sort: '+size');
sort には +createdAt、-createdAt、+name、-name、+size、-size を指定できます(+ が降順)。
untilId によるページネーションと整合するのは +createdAt(または sort の指定なし)だけです。それ以外のソートでは順序が変わる一方で、カーソルは引き続き ID でフィルターするため、ページ間で項目が抜けたり重複したりします。すべてのファイルを取得するには listAll() を使用してローカルでソートしてください。詳細はドライブヘルパーを参照してください。
ストリーム(全ファイル、フォルダ指定なし)
final all = await client.drive.stream(limit: 20, type: 'video/*');
名前で検索
final found = await client.drive.files.find(
name: 'photo.jpg',
folderId: myFolderId,
);
重複の確認
final exists = await client.drive.files.checkExistence(md5: fileMd5);
ファイルの詳細の取得
// ファイル ID で取得
final file = await client.drive.files.showByFileId(fileId);
// URL で取得
final file = await client.drive.files.showByUrl('https://example.com/file.jpg');
ファイルの属性の更新
final updated = await client.drive.files.update(
fileId: driveFile.id,
name: 'new-name.jpg',
comment: Optional('Updated alt text'), // Optional.null_() で削除する
isSensitive: false,
);
別のフォルダへ移動する場合:
await client.drive.files.update(
fileId: driveFile.id,
folderId: newFolderId,
);
ルートへ移動する場合:
await client.drive.files.update(
fileId: driveFile.id,
moveToRoot: true,
);
ファイルの削除
await client.drive.files.delete(fileId: driveFile.id);
フォルダ管理
// ルートのフォルダ一覧
final folders = await client.drive.folders.list();
// フォルダを作成
final folder = await client.drive.folders.create(
name: 'Vacation Photos',
);
// 入れ子のフォルダを作成
final nested = await client.drive.folders.create(
name: 'Day 1',
parentId: folder.id,
);
// フォルダ名を変更
await client.drive.folders.update(
folderId: folder.id,
name: 'Summer 2025',
);
// ルートへ移動
await client.drive.folders.update(
folderId: folder.id,
moveToRoot: true,
);
// フォルダを削除(空である必要があります)
await client.drive.folders.delete(folderId: folder.id);
ドライブの統計
final capacity = await client.drive.stats.getCapacity();
print('Used: ${capacity.usage} bytes');
print('Capacity: ${capacity.capacity} bytes');