tencent cloud

Cloud Object Storage

ドキュメントCloud Object Storage

Flutterからのダイレクトアップロード実践ガイド

ダウンロード
フォーカスモード
フォントサイズ
最終更新日: 2025-09-19 10:43:53

概要

このドキュメントでは、SDKに依存せず、シンプルなコードでFlutterクライアントからCloud Object Storage(COS)のバケットにファイルをダイレクトアップロードする方法について説明します。
注意:
このドキュメントの内容は、XMLバージョンのAPIに基づいています。

前提条件

1. COSコンソールにログインし、バケットを作成して、Bucket(バケット名)とRegion(リージョン名)を取得します。詳細については、バケットの作成ドキュメントをご参照ください。
2. CAMコンソールにログインし、プロジェクトのSecretIdとSecretKeyを取得します。

実装手順

全体的なロジックは以下の通りです:
1. クライアントがサーバーサイドのインターフェースを呼び出してファイルサフィックスを渡すと、サーバーサイドがサフィックスとタイムスタンプなどに基づいてCOSキーとダイレクトアップロード用のURLを生成します。
2. サーバーサイドはSTS SDKを通じて一時キーを取得します。
3. サーバーサイドは取得した一時キーペアを使用してダイレクトアップロードURLに署名し、URL、署名、トークンなどの情報を返します。
4. クライアントがステップ3で取得した情報を受け取った後、直接putリクエストを送信し、署名やトークンなどのヘッダーを付与してアップロードを実行します。
具体的なコードはFlutterサンプルをご参照ください。

サーバーサイド

注意:
本番環境にデプロイする際は、サーバーサイドにご自身のウェブサイトの権限検証を設定してください。
セキュリティ上、バックエンドは一時キーを取得した後、ダイレクトアップロードURLを生成し、直接署名を行います。詳細はサーバーサイドでの署名実践をご参照ください。
具体的な手順は以下の通りです:
1. STS SDKを通じて一時キーを取得します。
2. サフィックスに基づいてCOSキーとダイレクトアップロードURL関連の情報を生成します。
3. 一時キーを使用してダイレクトアップロードURLに署名し、URL、署名、トークンなどの情報を返します。
サーバーサイドの設定手順:
1. キー、バケット、およびリージョンを設定します。
var config = {
// Tencent Cloudのキーを取得します。権限が限定されたサブアカウントのキーを使用することを推奨します https://console.tencentcloud.com/cam/capi
secretId: process.env.COS_SECRET_ID,
secretKey: process.env.COS_SECRET_KEY,
// キーの有効期間
durationSeconds: 1800,
// ここにバケットとリージョンを入力します。例:test-1250000000、ap-guangzhou
bucket: process.env.PERSIST_BUCKET,
region: process.env.PERSIST_BUCKET_REGION,
// アップロードが制限されるサフィックス
extWhiteList: ['jpg', 'jpeg', 'png', 'gif', 'bmp'],
};
2. ターミナルで実行
npm install
3. サービスを起動
node app.js
ここでサーバーサイドの起動はしました。クライアントサイドのプロセスを開始できます。
他の言語や独自実装する場合は、以下の手順を参考にしてください。
1. サーバーサイドから一時キーを取得します。サーバーサイドはまず固定キー(SecretId、SecretKey)を使用してSTSサービスから一時キー(tmpSecretId、tmpSecretKey、sessionToken)を取得します。詳細はについては、一時キーの生成と利用ガイドまたはcos-sts-sdkドキュメントをご参照ください。
2. ダイレクトアップロードURLに署名し、authorizationを生成します。
3. ダイレクトアップロードURL、authorization、sessionTokenなどの情報を返します。クライアントは、ファイルをアップロードする際に取得した署名とsessionTokenを、それぞれリクエストヘッダーのauthorizationとx-cos-security-tokenフィールドに設定します。

クライアントサイド(Flutter)

具体的なコードは Flutterサンプル をご参照ください。

dioネットワークライブラリの利用

1. サーバーサイドからダイレクトアップロードと署名情報をリクエストします。
/// ダイレクトアップロードのURLや署名などを取得します
/// @param ext ファイルのサフィックス。ダイレクトアップロードすると、バックエンドはサフィックスに基づいてCOSキーを生成します
/// @return ダイレクトアップロード用のURLや署名など
static Future<Map<String, dynamic>> getStsDirectSign(String ext) async {
Dio dio = Dio();
//ダイレクトアップロード署名サービスのURL(本番環境では、正規のダイレクトアップロード署名サービスURLに置き換えてください)
//ダイレクトアップロード署名サービスのサーバーコード例はこちらを参考:https://github.com/tencentyun/cos-demo/blob/main/server/direct-sign/nodejs/app.js
//10.91.22.16はダイレクトアップロード署名サービスのサーバーアドレスです。例えば上記のnodeサービスなど、要するに、ダイレクトアップロード署名サービスサーバーにアクセスするためのURLです
Response response = await dio.get('http://10.91.22.16:3000/sts-direct-sign',
queryParameters: {'ext': ext});
if (response.statusCode == 200) {
if (kDebugMode) {
print(response.data);
}
if (response.data['code'] == 0) {
return response.data['data'];
} else {
throw Exception(
'getStsDirectSign error code: ${response.data['code']}, error message: ${response.data['message']}');
}
} else {
throw Exception(
'getStsDirectSign HTTP error code: ${response.statusCode}');
}
}
2. 取得したダイレクトアップロードと署名情報を使用して、ファイルのアップロードを開始します
/// ファイルをアップロード
/// @param filePath ファイルパス
/// @param progressCallback 進捗コールバック
static Future<void> upload(String filePath, ProgressCallback progressCallback) async {
String ext = path.extension(filePath).substring(1);
Map<String, dynamic> directTransferData;
try {
directTransferData = await getStsDirectSign(ext);
} catch (err) {
if (kDebugMode) {
print(err);
}
throw Exception("getStsDirectSign fail");
}
String cosHost = directTransferData['cosHost'];
String cosKey = directTransferData['cosKey'];
String authorization = directTransferData['authorization'];
String securityToken = directTransferData['securityToken'];
String url = 'https://$cosHost/$cosKey';
File file = File(filePath);
Options options = Options(
method: 'PUT',
headers: {
'Content-Length': await file.length(),
'Content-Type': 'application/octet-stream',
'Authorization': authorization,
'x-cos-security-token': securityToken,
'Host': cosHost,
},
);
try {
Dio dio = Dio();
Response response = await dio.put(url,
data: file.openRead(),
options: options, onSendProgress: (int sent, int total) {
double progress = sent / total;
if (kDebugMode) {
print('Progress: ${progress.toStringAsFixed(2)}');
}
progressCallback(sent, total);
});
if (response.statusCode == 200) {
if (kDebugMode) {
print('アップロードしました');
}
} else {
throw Exception("アップロードに失敗しました ${response.statusMessage}");
}
} catch (error) {
if (kDebugMode) {
print('Error: $error');
}
throw Exception("アップロードに失敗しました ${error.toString()}");
}
}

標準のHttp Clientネットワークライブラリの利用

1. サーバーサイドからダイレクトアップロードと署名情報をリクエストします。
/// ダイレクトアップロード用のURLと署名などを取得します
/// @param ext ファイルのサフィックス。ダイレクトアップロードすると、バックエンドは拡張子に基づいてCOSキーを生成します
/// @return ダイレクトアップロード用のURLと署名など
static Future<Map<String, dynamic>> _getStsDirectSign(String ext) async {
HttpClient httpClient = HttpClient();
//ダイレクトアップロード署名サービスのサーバーURL(本番環境では、正規のダイレクトアップロード署名サービスURLに置き換えてください)
//ダイレクトアップロード署名サービスのサーバーコード例はこちらを参考:https://github.com/tencentyun/cos-demo/blob/main/server/direct-sign/nodejs/app.js
//10.91.22.16はダイレクトアップロード署名サービスのサーバーアドレスです。例えば上記のnodeサービスなど、要するに、ダイレクトアップロード署名サービスサーバーにアクセスするためのURLです
HttpClientRequest request = await httpClient
.getUrl(Uri.parse("http://10.91.22.16:3000/sts-direct-sign?ext=$ext"));
HttpClientResponse response = await request.close();
String responseBody = await response.transform(utf8.decoder).join();
if (response.statusCode == 200) {
Map<String, dynamic> json = jsonDecode(responseBody);
if (kDebugMode) {
print(json);
}
httpClient.close();
if (json['code'] == 0) {
return json['data'];
} else {
throw Exception(
'getStsDirectSign error code: ${json['code']}, error message: ${json['message']}');
}
} else {
httpClient.close();
throw Exception(
'getStsDirectSign HTTP error code: ${response.statusCode}');
}
}
2. 取得したダイレクトアップロードと署名情報を使用して、ファイルのアップロードを開始します。
/// ファイルをアップロード
/// @param filePath ファイルパス
/// @param progressCallback 進捗コールバック
static Future<void> upload(String filePath, ProgressCallback progressCallback) async {
// ダイレクトアップロードの署名情報などを取得
String ext = path.extension(filePath).substring(1);
Map<String, dynamic> directTransferData;
try {
directTransferData = await _getStsDirectSign(ext);
} catch (err) {
if (kDebugMode) {
print(err);
}
throw Exception("getStsDirectSign fail");
}

String cosHost = directTransferData['cosHost'];
String cosKey = directTransferData['cosKey'];
String authorization = directTransferData['authorization'];
String securityToken = directTransferData['securityToken'];
String url = 'https://$cosHost/$cosKey';

File file = File(filePath);
int fileSize = await file.length();
HttpClient httpClient = HttpClient();
HttpClientRequest request = await httpClient.putUrl(Uri.parse(url));
request.headers.set('Content-Type', 'application/octet-stream');
request.headers.set('Content-Length', fileSize.toString());
request.headers.set('Authorization', authorization);
request.headers.set('x-cos-security-token', securityToken);
request.headers.set('Host', cosHost);
request.contentLength = fileSize;
Stream<List<int>> stream = file.openRead();
int bytesSent = 0;
stream.listen(
(List<int> chunk) {
bytesSent += chunk.length;
double progress = bytesSent / fileSize;
if (kDebugMode) {
print('Progress: ${progress.toStringAsFixed(2)}');
}
progressCallback(bytesSent, fileSize);
request.add(chunk);
},
onDone: () async {
HttpClientResponse response = await request.close();
if (response.statusCode == 200) {
if (kDebugMode) {
print('アップロードしました');
}
} else {
throw Exception("アップロードに失敗しました $response");
}
},
onError: (error) {
if (kDebugMode) {
print('Error: $error');
}
throw Exception("アップロードに失敗しました ${error.toString()}");
},
cancelOnError: true,
);
}

関連ドキュメント

他のAPI呼び出しのニーズがある場合は、Flutter SDK をご参照ください。

ヘルプとサポート

この記事はお役に立ちましたか?

フィードバック