'Flutter :: Amazon S3 Image Upload
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.
Solution 1:[1]
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}" }
]
}
''';
}
}
Solution 2:[2]
I did file uploading in s3bucket using simple_s3: ^0.3.2 package. here is the code.
Future<String> uploadFile(
BuildContext context, String filePath) async {
String bucketName = "Bucket name";
String cognitoPoolId = "Pool id";
String result = await SimpleS3().uploadFile(
File(filePath),
bucketName,
cognitoPoolId,
AWSRegions.euWest1,
useTimeStamp: false, //true if you want timestamp in uploaded file path
accessControl: S3AccessControl.private,
s3FolderPath: "Here your folder name",
debugLog: true);
return result;
}
Above method will return path of uploaded file in S3bucket.
Solution 3:[3]
import 'package:flutter_amazon_s3/flutter_amazon_s3.dart';
Future getImage() async {
var _image = await ImagePicker.pickImage(source: ImageSource.gallery);
print('getImage ${image.path}');//print image path
String uploadedImageUrl = await FlutterAmazonS3.uploadImage(
_image.path, BUCKET_NAME, IDENTITY_POOL_ID);
print('uploadedImageUrl ===== $uploadedImageUrl');
}
I am using this code to upload image on S3, its seems not to be working. I am not getting uploadedImageUrl
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Hardik Hirpara |
| Solution 3 | Priyanka Barasker |
