我的 flutter 应用程序使用 firebase 作为后端,但我需要将媒体文件(照片和视频)存储在我的 s3 存储桶中。任务是将从图像选择器检索到的媒体上传到 s3 并取回 url,然后可以将其作为字符串存储在我的 firebase 数据库中。
问题是 dart 2 缺少 aws 库或 api。我在 pub 中找到了 3 个,但其中 2 个与 dart 2 不兼容,并且 1 正在开发中。有没有人使用 dart 2 在 flutter 中实现这一点?欢迎任何建议。谢谢。
我找到的包是 (pub.dartlang.org):aws_client、aws_interop、amazon_s3
最佳答案
有几种方法可以做到这一点。一种方法是sign your request与 Signature V4并将您的文件 POST
到 S3。
首先,创建一个策略助手:
import 'dart:convert';
import 'package:amazon_cognito_identity_dart/sig_v4.dart';
class Policy {
String expiration;
String region;
String bucket;
String key;
String credential;
String datetime;
int maxFileSize;
Policy(this.key, this.bucket, this.datetime, this.expiration, this.credential,
this.maxFileSize,
{this.region = 'us-east-1'});
factory Policy.fromS3PresignedPost(
String key,
String bucket,
String accessKeyId,
int expiryMinutes,
int maxFileSize, {
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 p = Policy(key, bucket, datetime, expiration, cred, maxFileSize,
region: region);
return p;
}
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}" }
]
}
''';
}
}
然后,使用您的策略助手签署您的请求并通过 http.MultipartRequest
上传:
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:async/async.dart';
import 'package:http/http.dart' as http;
import 'package:test/test.dart';
import 'package:amazon_cognito_identity_dart/sig_v4.dart';
import './policy.dart';
void main() {
const _accessKeyId = 'AKXXXXXXXXXXXXXXXXXX';
const _secretKeyId = 'xxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxx';
const _region = 'ap-southeast-1';
const _s3Endpoint =
'https://bucketname.s3-ap-southeast-1.amazonaws.com';
final file = File(path.join('/path/to/file', 'square-cinnamon.jpg'));
final stream = http.ByteStream(DelegatingStream.typed(file.openRead()));
final length = await file.length();
final uri = Uri.parse(_s3Endpoint);
final req = http.MultipartRequest("POST", uri);
final multipartFile = http.MultipartFile('file', stream, length,
filename: path.basename(file.path));
final policy = Policy.fromS3PresignedPost('uploaded/square-cinnamon.jpg',
'bucketname', _accessKeyId, 15, length,
region: _region);
final key =
SigV4.calculateSigningKey(_secretKeyId, policy.datetime, _region, 's3');
final signature = SigV4.calculateSignature(key, policy.encode());
req.files.add(multipartFile);
req.fields['key'] = policy.key;
req.fields['acl'] = 'public-read';
req.fields['X-Amz-Credential'] = policy.credential;
req.fields['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256';
req.fields['X-Amz-Date'] = policy.datetime;
req.fields['Policy'] = policy.encode();
req.fields['X-Amz-Signature'] = signature;
try {
final res = await req.send();
await for (var value in res.stream.transform(utf8.decoder)) {
print(value);
}
} catch (e) {
print(e.toString());
}
}
请注意,此方法需要您提供您的访问 key 和 secret key 。如果您使用像 Cognito 这样的服务,建议您获取一个临时的 Access Key 和 Secret Key。找到使用临时访问的示例 here .
免责声明:我是 Signature V4 package 的原作者.
关于amazon-web-services - 在 Flutter 中从 AWS S3 上传和获取媒体文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53811487/
相关文章:
android - 即使应用程序关闭,也在后台运行 Dart 和 Flutter 中的定期任务
android - 在 Dismissible Widget 上禁用关闭方向
datetime - Dart/Flutter 默认日期格式
android - 使用 pushNamed() 从屏幕错误中 flutter 返回数据
dart - Flutter:StatelessWidget.build 被多次调用
dart - 如何使 Sink
java - 在 Flutter 应用程序中使用 Java 或其他语言
android - 如何在 Flutter 中删除 Firebase 云消息传递 token