dart_aliyun_oss 1.2.0
dart_aliyun_oss: ^1.2.0 copied to clipboard
Dart client SDK for Alibaba Cloud Object Storage Service (OSS). Supports file upload, download, multipart upload, signed URLs and more.
Alibaba Cloud OSS Dart SDK #
This is a Dart client SDK for Alibaba Cloud Object Storage Service (OSS), providing simple and easy-to-use APIs to access Alibaba Cloud OSS services.
Features #
- File upload and download
- Large file multipart upload
- Upload and download progress monitoring
- Multipart upload management operations (list, abort, etc.)
- Support for both V1 and V4 signature algorithms
Installation #
dependencies:
dart_aliyun_oss: ^1.1.0
Then run:
dart pub get
Usage Examples #
Initialization #
import 'package:dart_aliyun_oss/dart_aliyun_oss.dart';
// Initialize OSS client
final oss = OSSClient.init(
OSSConfig(
endpoint: 'your-endpoint.aliyuncs.com', // e.g. oss-cn-hangzhou.aliyuncs.com
region: 'your-region', // e.g. cn-hangzhou
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucketName: 'your-bucket-name',
),
);
Using Custom Domain (CNAME) #
If you have bound a custom domain to your OSS bucket, you can use it instead of the default OSS endpoint:
// Initialize OSS client with custom domain
final oss = OSSClient.init(
OSSConfig.static(
endpoint: 'img.example.com', // Your custom domain
region: 'cn-hangzhou',
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucketName: 'your-bucket-name',
cname: true, // Enable custom domain
),
);
Prerequisites for using custom domain:
- You must have bound your custom domain to the OSS bucket in the Alibaba Cloud console
- You must have added a CNAME record pointing your custom domain to the OSS endpoint
- When using custom domain, bucket-level operations (like
listBuckets
) are not available
Simple Upload #
The SDK supports uploading different types of data:
Upload File
Future<void> uploadFile() async {
final file = File('path/to/your/file.txt');
await oss.putObject(
file,
'example/file.txt', // OSS object key
params: OSSRequestParams(
onSendProgress: (int count, int total) {
print('Upload progress: ${(count / total * 100).toStringAsFixed(2)}%');
},
),
);
}
Upload String Content
Future<void> uploadString() async {
const String content = '''
This is a text file uploaded from string content.
Supports multi-line text content.
Timestamp: 2024-01-01 12:00:00
''';
await oss.putObjectFromString(
content,
'example/text_content.txt',
params: OSSRequestParams(
onSendProgress: (int count, int total) {
print('String upload progress: ${(count / total * 100).toStringAsFixed(2)}%');
},
),
);
}
Upload Byte Array
import 'dart:typed_data';
Future<void> uploadBytes() async {
// Create sample byte array (e.g., binary data)
final Uint8List bytes = Uint8List.fromList([
// File header (simulating PNG file header)
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
// Some sample data
...List<int>.generate(1024, (index) => index % 256),
]);
await oss.putObjectFromBytes(
bytes,
'example/binary_data.bin',
params: OSSRequestParams(
onSendProgress: (int count, int total) {
print('Bytes upload progress: ${(count / total * 100).toStringAsFixed(2)}%');
},
),
);
}
Download File #
Future<void> downloadFile() async {
final ossObjectKey = 'example/file.txt';
final downloadPath = 'path/to/save/file.txt';
final response = await oss.getObject(
ossObjectKey,
params: OSSRequestParams(
onReceiveProgress: (int count, int total) {
print('Download progress: ${(count / total * 100).toStringAsFixed(2)}%');
},
),
);
final File downloadFile = File(downloadPath);
await downloadFile.parent.create(recursive: true);
await downloadFile.writeAsBytes(response.data);
}
Multipart Upload #
Future<void> multipartUpload() async {
final file = File('path/to/large/file.mp4');
final ossObjectKey = 'videos/large_file.mp4';
final completeResponse = await oss.multipartUpload(
file,
ossObjectKey,
params: OSSRequestParams(
onSendProgress: (count, total) {
print('Overall progress: ${(count / total * 100).toStringAsFixed(2)}%');
},
),
);
print('Multipart upload completed successfully!');
}
Using Query Parameters #
// List parts of a multipart upload with query parameters
final response = await oss.listParts(
'example/large_file.mp4',
'your-upload-id',
params: OSSRequestParams(
queryParameters: {
'max-parts': 100,
'part-number-marker': 5,
},
),
);
// Get object with specific version using query parameters
final response = await oss.getObject(
'example/file.txt',
params: OSSRequestParams(
queryParameters: {
'versionId': 'your-version-id',
},
),
);
Using STS Temporary Tokens #
STS (Security Token Service) provides temporary credentials for secure access to OSS resources. This SDK supports both static STS tokens and dynamic token refresh.
Method 1: Static STS Token
// Initialize client with static STS temporary token
final OSSConfig configWithSTS = OSSConfig.static(
accessKeyId: 'STS.your-sts-access-key-id',
accessKeySecret: 'your-sts-access-key-secret',
securityToken: 'your-sts-security-token', // STS temporary security token
bucketName: 'your-bucket-name',
endpoint: 'oss-cn-hangzhou.aliyuncs.com',
region: 'cn-hangzhou',
);
final OSSClient ossWithSTS = OSSClient.init(configWithSTS);
// Upload file using STS temporary token
await ossWithSTS.putObject(
File('path/to/file.txt'),
'example/file.txt',
);
Method 2: Dynamic STS Token Refresh (Recommended)
// STS Token Manager for automatic token refresh
class StsTokenManager {
String? _accessKeyId;
String? _accessKeySecret;
String? _securityToken;
DateTime? _expireTime;
String get accessKeyId {
_refreshIfNeeded();
return _accessKeyId!;
}
String get accessKeySecret {
_refreshIfNeeded();
return _accessKeySecret!;
}
String? get securityToken {
_refreshIfNeeded();
return _securityToken;
}
void _refreshIfNeeded() {
if (_expireTime == null ||
DateTime.now().isAfter(_expireTime!.subtract(Duration(minutes: 5)))) {
_refreshStsToken();
}
}
void _refreshStsToken() {
// Call your STS service to get new temporary credentials
// Replace this with actual STS API call
_accessKeyId = 'STS.new_access_key_id';
_accessKeySecret = 'new_access_key_secret';
_securityToken = 'new_security_token';
_expireTime = DateTime.now().add(Duration(hours: 1));
}
}
// Initialize client with dynamic STS token refresh
final stsManager = StsTokenManager();
final OSSClient ossWithDynamicSTS = OSSClient.init(
OSSConfig(
accessKeyIdProvider: () => stsManager.accessKeyId,
accessKeySecretProvider: () => stsManager.accessKeySecret,
securityTokenProvider: () => stsManager.securityToken,
bucketName: 'your-bucket-name',
endpoint: 'oss-cn-hangzhou.aliyuncs.com',
region: 'cn-hangzhou',
),
);
// The client will automatically use refreshed tokens for all operations
await ossWithDynamicSTS.putObject(
File('path/to/file.txt'),
'example/file.txt',
);
Generate Signed URL #
// Generate a signed URL with V1 signature algorithm
final String signedUrlV1 = oss.signedUrl(
'example/test.txt',
method: 'GET',
expires: 3600, // URL expires in 1 hour
isV1Signature: true,
);
// Generate a signed URL with V4 signature algorithm
final String signedUrlV4 = oss.signedUrl(
'example/test.txt',
method: 'GET',
expires: 3600,
isV1Signature: false,
);
More Examples #
For more examples, please refer to the example/example.dart
file.
Notes #
-
Do not hardcode your AccessKey information in production code. It is recommended to use environment variables or other secure credential management methods.
-
When using multipart upload, if the upload process is interrupted, make sure to call the
abortMultipartUpload
method to clean up incomplete multipart uploads.
License #
This project is licensed under the MIT License - see the LICENSE file for details.