Flutter :: Amazon S3图像上传 [英] Flutter :: Amazon S3 Image Upload

查看:91
本文介绍了Flutter :: Amazon S3图像上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

https://pub.dartlang.org/packages/flutter_amazon_s3

我尝试将使用该库的映像突然上传到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.

推荐答案

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}" }
  ]
}
''';
  }
}

使用此代码,您可以发送图像,但是不幸的是,我无法在发出请求时更改文件的元数据,从而使其成为 binary/octet-stream 而不是 image/jpeg 仅当您在应用程序外部使用图片时,这才是问题.

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.

在此实施方式中,我使用了 Dio 和Amazon Cognito Identity Dart软件包,您可以使用 Amazon Cognito Identity Dart Amazon Cognito Identity Dart 2 ,由于存储库仍处于活动状态,我建议使用第二种方法.

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.

更新,固定的二进制/八进制流问题

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}" }
  ]
}
''';
  }
}

这篇关于Flutter :: Amazon S3图像上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆