Flutter :: Amazon S3 Image Upload
3,753
class UploadAWS {
Future<String> uploadImage(File image, String path) async {
final Dio _client = Dio();
_client.interceptors.add(LogInterceptor());
final int length = await image.length();
final String filename = 'testFile.jpg';
final String key = path + filename;
final Policy policy = Policy.fromS3PreSignedPost(
key,
AWSBucket,
15,
AWSaccessKey,
length,
AWSsessionToken,
region: AWSregion,
);
final List<int> signKey =
SigV4.calculateSigningKey(AWSsecretKey, policy.datetime, AWSregion, AWSservice);
final String signature = SigV4.calculateSignature(signKey, policy.encode());
final FormData formData = FormData.fromMap({
'key': policy.key,
'acl': 'public-read',
'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
'X-Amz-Credential': policy.credential,
'X-Amz-Date': policy.datetime,
'Policy': policy.encode(),
'X-Amz-Signature': signature,
'x-amz-security-token': AWSsessionToken,
'file': await MultipartFile.fromFile(
image.path,
filename: filename,
)
});
Response response = await _client.post('https://$AWSBucket.s3.amazonaws.com', data: formData);
_client.close();
return response.headers.map['location'].first;
}
}
class Policy {
String expiration;
String region;
String bucket;
String key;
String credential;
String datetime;
String sessionToken;
int maxFileSize;
Policy(this.key, this.bucket, this.datetime, this.expiration, this.credential,
this.maxFileSize, this.sessionToken,
{this.region = AWS_REGION_FTALK});
factory Policy.fromS3PreSignedPost(
String key,
String bucket,
int expiryMinutes,
String accessKeyId,
int maxFileSize,
String sessionToken, {
String region,
}) {
final datetime = SigV4.generateDatetime();
final expiration = (DateTime.now())
.add(Duration(minutes: expiryMinutes))
.toUtc()
.toString()
.split(' ')
.join('T');
final cred =
'$accessKeyId/${SigV4.buildCredentialScope(datetime, region, 's3')}';
final policy = Policy(
key, bucket, datetime, expiration, cred, maxFileSize, sessionToken,
region: region);
return policy;
}
String encode() {
final bytes = utf8.encode(toString());
return base64.encode(bytes);
}
@override
String toString() {
return '''
{ "expiration": "${this.expiration}",
"conditions": [
{"bucket": "${this.bucket}"},
["starts-with", "\$key", "${this.key}"],
{"acl": "public-read"},
["content-length-range", 1, ${this.maxFileSize}],
{"x-amz-credential": "${this.credential}"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": "${this.datetime}" },
{"x-amz-security-token": "${this.sessionToken}" }
]
}
''';
}
}
With this code you can send the image, but unfortunately I can't change the file's metadata when making the request, making it binary/octet-stream instead of image/jpeg, this is only a problem if you use the image outside the application.
In this implementation I used the Dio and Amazon Cognito Identity Dart packages, you can use either Amazon Cognito Identity Dart or Amazon Cognito Identity Dart 2, I recommend the second option, as the repository is still active.
UPDATE, FIXED BINARY/OCTET-STREAM PROBLEM
class UploadAWS {
Future<String> uploadImage(File image, String path) async {
final Dio _client = Dio();
_client.interceptors.add(LogInterceptor());
final int length = await image.length();
final String filename = 'testFile.jpg';
final String key = path + filename;
final Policy policy = Policy.fromS3PreSignedPost(
key,
AWSBucket,
15,
AWSaccessKey,
length,
AWSsessionToken,
region: AWSregion,
);
final List<int> signKey =
SigV4.calculateSigningKey(AWSsecretKey, policy.datetime, AWSregion, AWSservice);
final String signature = SigV4.calculateSignature(signKey, policy.encode());
final FormData formData = FormData.fromMap({
'key': policy.key,
'acl': 'public-read',
'X-Amz-Algorithm': 'AWS4-HMAC-SHA256',
'X-Amz-Credential': policy.credential,
'X-Amz-Date': policy.datetime,
'Policy': policy.encode(),
'X-Amz-Signature': signature,
'x-amz-security-token': AWSsessionToken,
'Content-Type': 'image/jpeg',
'file': await MultipartFile.fromFile(
image.path,
filename: filename,
)
});
Response response = await _client.post('https://$AWSBucket.s3.amazonaws.com', data: formData);
_client.close();
return response.headers.map['location'].first;
}
}
class Policy {
String expiration;
String region;
String bucket;
String key;
String credential;
String datetime;
String sessionToken;
int maxFileSize;
Policy(this.key, this.bucket, this.datetime, this.expiration, this.credential,
this.maxFileSize, this.sessionToken,
{this.region = AWS_REGION_FTALK});
factory Policy.fromS3PreSignedPost(
String key,
String bucket,
int expiryMinutes,
String accessKeyId,
int maxFileSize,
String sessionToken, {
String region,
}) {
final datetime = SigV4.generateDatetime();
final expiration = (DateTime.now())
.add(Duration(minutes: expiryMinutes))
.toUtc()
.toString()
.split(' ')
.join('T');
final cred =
'$accessKeyId/${SigV4.buildCredentialScope(datetime, region, 's3')}';
final policy = Policy(
key, bucket, datetime, expiration, cred, maxFileSize, sessionToken,
region: region);
return policy;
}
String encode() {
final bytes = utf8.encode(toString());
return base64.encode(bytes);
}
@override
String toString() {
return '''
{ "expiration": "${this.expiration}",
"conditions": [
{"bucket": "${this.bucket}"},
["starts-with", "\$key", "${this.key}"],
["starts-with", "\$Content-Type", "image/"],
{"acl": "public-read"},
["content-length-range", 1, ${this.maxFileSize}],
{"x-amz-credential": "${this.credential}"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": "${this.datetime}" },
{"x-amz-security-token": "${this.sessionToken}" }
]
}
''';
}
}
Author by
Vishal Dhaduk
Updated on December 11, 2022Comments
-
Vishal Dhaduk over 1 year
https://pub.dartlang.org/packages/flutter_amazon_s3
I try to upload Image using this lib in flutter to Amazon S3 but not working any solution?
import 'package:flutter_amazon_s3/flutter_amazon_s3.dart'; String uploadedImageUrl = await FlutterAmazonS3.uploadImage( _image.path, BUCKET_NAME, IDENTITY_POOL_ID); print("_uploadImageToAWS uploadedImageUrl ::" + uploadedImageUrl);
but nothing return in log, even no any error.
-
Jawand Singh almost 5 yearscan you share, the code you have written and the errors you are getting? That will help everyone.
-
Jignesh Patel almost 4 years@Vishal Dhaduk Did you find to upload image on s3? because i implemented it but i got this exception below Unhandled Exception: PlatformException(error, Can't downgrade database from version 6 to 5, null) Can you help me to solved out?
-
-
Sukhi over 4 yearsWelcome to Stackoverflow ! This is not an answer, Priyanka; it's a comment. You might want to delete your answer. Moreover, your code looks similar Vishal's one.