目前為止,阿里雲官方並沒有dart
版本的oss sdk,所以才開發了這個外掛flutter_oss_aliyun
提供對oss sdk的支援。
flutter_oss_aliyun
一個訪問阿里雲oss並且支援STS臨時訪問憑證訪問OSS的flutter庫,基本上涵蓋阿里雲oss sdk的所有功能。⭐
flutter pub: https://pub.dev/packages/flutter_oss_aliyun
github : https://github.com/huhx/flutter_oss_aliyun
oss sts document: https://help.aliyun.com/document_detail/100624.html
? 初始化Client
新增依賴
dependencies:
flutter_oss_aliyun: ^6.2.2
初始化oss client, 這裡我們提供兩種方式
1. 提供sts server地址,需要後端新增這個api
Client.init(
stsUrl: "server url get sts token",
ossEndpoint: "oss-cn-beijing.aliyuncs.com",
bucketName: "bucket name",
);
後端api至少需要返回以下資料:
{
"AccessKeyId": "AccessKeyId",
"AccessKeySecret": "AccessKeySecret",
"SecurityToken": "SecurityToken",
"Expiration": "2022-03-22T11:33:06Z"
}
2. 自定義authGetter得到Auth
Client.init(
ossEndpoint: "oss-cn-beijing.aliyuncs.com",
bucketName: "bucketName",
authGetter: _authGetter
);
Auth _authGetter() {
return Auth(
accessKey: "accessKey",
accessSecret: 'accessSecret',
expire: '2023-02-23T14:02:46Z',
secureToken: 'token',
);
}
你可以傳入自定義的Dio
在init函式中,你可以傳入dio,做到dio的定製化。比如日誌或者其他的interceptors.
Client.init(
stsUrl: "server url get sts token",
ossEndpoint: "oss-cn-beijing.aliyuncs.com",
bucketName: "bucket name",
dio: Dio(BaseOptions(connectTimeout: 9000)),
);
? 使用
- 檔案上傳
- 追加檔案上傳
- 跨bucket檔案複製
- 取消檔案上傳
- 批次檔案上傳
- 本地檔案上傳
- 批次本地檔案上傳
- 檔案下載
- 檔案下載並儲存
- 檔案刪除
- 批次檔案刪除
- 獲取已簽名的檔案url
- 獲取多個已簽名的檔案url
- 列舉所有的儲存空間
- 列舉儲存空間中所有檔案
- 獲取bucket資訊
- 獲取bucket的儲容量以及檔案數量
- 獲取檔案元資訊
- regions的查詢
- bucket acl的操作
- bucket policy的操作
檔案上傳
關於callback的使用: https://help.aliyun.com/document_detail/31989.htm?spm=a2c4g.11186623.0.0.73a830ffn45LMY#reference-zkm-311-hgb
final bytes = "file bytes".codeUnits;
await Client().putObject(
bytes,
"test.txt",
option: PutRequestOption(
onSendProgress: (count, total) {
print("send: count = $count, and total = $total");
},
onReceiveProgress: (count, total) {
print("receive: count = $count, and total = $total");
},
override: false,
aclModel: AclMode.publicRead,
storageType: StorageType.ia,
headers: {"cache-control": "no-cache"},
callback: Callback(
callbackUrl: "callback url",
callbackBody: "{\"mimeType\":\${mimeType}, \"filepath\":\${object},\"size\":\${size},\"bucket\":\${bucket},\"phone\":\${x:phone}}",
callbackVar: {"x:phone": "android"},
calbackBodyType: CalbackBodyType.json,
),
),
);
PutRequestOption 欄位說明,欄位皆為非必需
Filed | Default value | Description |
---|---|---|
override | true | true: 允許覆蓋同名Object false: 禁止覆蓋同名Object |
aclModel | inherited | 1. publicWrite: 任何人(包括匿名訪問者)都可以對該Object進行讀寫操作 2. publicRead: 只有該Object的擁有者可以對該Object進行寫操作,任何人(包括匿名訪問者)都可以對該Object進行讀操作 3. private: 只有Object的擁有者可以對該Object進行讀寫操作,其他人無法訪問該Object 4. inherited: 該Object遵循Bucket的讀寫許可權,即Bucket是什麼許可權,Object就是什麼許可權 參考文件: https://help.aliyun.com/document_detail/100676.htm?spm=a2c4g.11186623.0.0.56637952SnxOWV#concept-blw-yqm-2gb |
storageType | Standard | 參考文件: https://help.aliyun.com/document_detail/51374.htm?spm=a2c4g.11186623.0.0.56632b55htpEQX#concept-fcn-3xt-tdb |
追加檔案上傳
final Response<dynamic> resp = await Client().appendObject(
Uint8List.fromList(utf8.encode("Hello World")),
"test_append.txt",
);
final Response<dynamic> resp2 = await Client().appendObject(
position: int.parse(resp.headers["x-oss-next-append-position"]?[0]),
Uint8List.fromList(utf8.encode(", Fluter.")),
"test_append.txt",
);
跨bucket複製檔案
final Response<dynamic> resp = await Client().copyObject(
const CopyRequestOption(
sourceFileKey: 'test.csv',
targetFileKey: "test_copy.csv",
targetBucketName: "bucket_2"
),
);
取消檔案上傳
final CancelToken cancelToken = CancelToken();
final bytes = ("long long bytes" * 1000).codeUnits;
Client().putObject(
Uint8List.fromList(utf8.encode(string)),
"cancel_token_test.txt",
cancelToken: cancelToken,
option: PutRequestOption(
onSendProgress: (count, total) {
if (kDebugMode) {
print("send: count = $count, and total = $total");
}
if (count > 56) {
cancelToken.cancel("cancel the uploading.");
}
},
),
).then((response) {
// success
print("upload success = ${response.statusCode}");
}).catchError((err) {
if (CancelToken.isCancel(err)) {
print("error message = ${err.message}");
} else {
// handle other errors
}
});
批次檔案上傳
await Client().putObjects([
AssetEntity(
filename: "filename1.txt",
bytes: "files1".codeUnits,
option: PutRequestOption(
onSendProgress: (count, total) {
print("send: count = $count, and total = $total");
},
onReceiveProgress: (count, total) {
print("receive: count = $count, and total = $total");
},
aclModel: AclMode.private,
),
),
AssetEntity(filename: "filename2.txt", bytes: "files2".codeUnits),
]);
本地檔案上傳
final Response<dynamic> resp = await Client().putObjectFile(
"/Users/aaa.pdf",
fileKey: "aaa.png",
option: PutRequestOption(
onSendProgress: (count, total) {
print("send: count = $count, and total = $total");
},
onReceiveProgress: (count, total) {
print("receive: count = $count, and total = $total");
},
aclModel: AclMode.private,
),
);
批次本地檔案上傳
final List<Response<dynamic>> resp = await Client().putObjectFiles(
[
AssetFileEntity(
filepath: "//Users/private.txt",
option: PutRequestOption(
onSendProgress: (count, total) {
print("send: count = $count, and total = $total");
},
onReceiveProgress: (count, total) {
print("receive: count = $count, and total = $total");
},
override: false,
aclModel: AclMode.private,
),
),
AssetFileEntity(
filepath: "//Users/splash.png",
filename: "aaa.png",
option: PutRequestOption(
onSendProgress: (count, total) {
print("send: count = $count, and total = $total");
},
onReceiveProgress: (count, total) {
print("receive: count = $count, and total = $total");
},
override: true,
),
),
],
);
檔案下載
await Client().getObject(
"test.txt",
onReceiveProgress: (count, total) {
debugPrint("received = $count, total = $total");
},
);
檔案下載並儲存
await Client().downloadObject(
"test.txt",
"./example/test.txt",
onReceiveProgress: (count, total) {
debugPrint("received = $count, total = $total");
},
);
檔案刪除
await Client().deleteObject("test.txt");
批次檔案刪除
await Client().deleteObjects(["filename1.txt", "filename2.txt"]);
獲取已簽名的檔案url
需要注意的是: 這個操作並不安全
,因為url包含security-token資訊,即使過期時間比較短. 這個url可以直接在瀏覽器訪問
final String url = await Client().getSignedUrl("filename1.txt");
獲取多個已簽名的檔案url
需要注意的是: 這個操作並不安全
,因為url包含security-token資訊,即使過期時間比較短
final Map<String, String> result = await Client().getSignedUrls(["test.txt", "filename1.txt"]);
列舉所有的儲存空間
列舉請求者擁有的所有儲存空間(Bucket)。您還可以透過設定prefix、marker或者max-keys引數列舉滿足指定條件的儲存空間。參考: https://help.aliyun.com/document_detail/31957.html
final Response<dynamic> resp = await Client().listBuckets({"max-keys": 2});
列舉儲存空間中所有檔案
介面用於列舉儲存空間(Bucket)中所有檔案(Object)的資訊。請求引數和返回結果,請參考: https://help.aliyun.com/document_detail/187544.html
final Response<dynamic> resp = await Client().listFiles({});
獲取bucket資訊
檢視儲存空間(Bucket)的相關資訊。返回結果請參考: https://help.aliyun.com/document_detail/31968.html
final Response<dynamic> resp = await Client().getBucketInfo();
獲取bucket的儲容量以及檔案數量
獲取指定儲存空間(Bucket)的儲存容量以及檔案(Object)數量。返回結果請參考: https://help.aliyun.com/document_detail/426056.html
final Response<dynamic> resp = await Client().getBucketStat();
獲取檔案元資訊
final Response<dynamic> resp = await Client().getObjectMeta("huhx.csv");
regions的查詢
- 查詢所有
final Response<dynamic> resp = await Client().getAllRegions();
- 查詢特定
final Response<dynamic> resp = await Client().getRegion("oss-ap-northeast-1");
bucket acl的操作
- 查詢
final Response<dynamic> resp = await Client().getBucketAcl(
bucketName: "bucket-name",
);
- 更新
final Response<dynamic> resp = await Client().putBucketAcl(
AciMode.publicRead,
bucketName: "bucket-name",
);
bucket policy的操作
- 查詢
final Response<dynamic> resp = await Client().getBucketPolicy(
bucketName: "bucket-name",
);
- 更新
final Response<dynamic> resp = await Client().putBucketPolicy(
{},
bucketName: "bucket-name",
);
- 刪除
final Response<dynamic> resp = await Client().deleteBucketPolicy(
bucketName: "bucket-name",
);