Загружайте и извлекайте мультимедийные файлы из AWS S3 во Flutter - PullRequest
0 голосов
/ 17 декабря 2018

Мое приложение флаттера использует Firebase в качестве бэкэнда, но мне нужно хранить медиа-файлы (фото и видео) в моем контейнере s3.Миссия состоит в том, чтобы загрузить медиафайлы, извлеченные из средства выбора изображений, в s3 и вернуть URL-адрес, который затем можно сохранить в виде строки в моей базе данных firebase.

Проблема заключается в нехватке библиотек aws или API длядротик 2. Я нашел 3 в пабе, но 2 из них были несовместимы с дротиком 2, а 1 находился в стадии разработки.Кто-нибудь реализовал это во флаттере, используя дротик 2?Любые предложения приветствуются.Спасибо.

Пакеты, которые я нашел, были (pub.dartlang.org): aws_client, aws_interop, amazon_s3

Ответы [ 3 ]

0 голосов
/ 04 марта 2019

Есть несколько способов сделать это.Один из способов - подписать ваш запрос с помощью Подпись 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());
  }
}

Обратите внимание, что для этого метода требуется предоставить свой ключ доступа и секретный ключ.Если вы используете такой сервис, как Cognito, рекомендуется получить временный ключ доступа и секретный ключ.Примеры использования временного доступа найдены здесь .

Отказ от ответственности: я являюсь первоначальным автором пакета Signature V4 .

0 голосов
/ 24 августа 2019

Вы можете использовать пакет amazon_s3_cognito для загрузки и удаления изображений в amazon s3.

Я являюсь автором плагина, и мы успешно используем этот плагин во многих наших проектах.

import 'package:amazon_s3_cognito/amazon_s3_cognito.dart';
import 'package:amazon_s3_cognito/aws_region.dart';

String uploadedImageUrl = await AmazonS3Cognito.uploadImage(
          _image.path, BUCKET_NAME, IDENTITY_POOL_ID);


//Use the below code to upload an image to amazon s3 server
String uploadedImageUrl = await AmazonS3Cognito.upload(
            _image.path,
            BUCKET_NAME,
            IDENTITY_POOL_ID,
            IMAGE_NAME,
            AwsRegion.US_EAST_1,
            AwsRegion.AP_SOUTHEAST_1)

//use below code to delete an image
 String result = AmazonS3Cognito.delete(
            BUCKET_NAME,
            IDENTITY_POOL_ID,
            IMAGE_NAME,
            AwsRegion.US_EAST_1,
            AwsRegion.AP_SOUTHEAST_1)

Для извлечения изображений вы можете использовать cached_network_image package

CachedNetworkImage можно использовать напрямую или через ImageProvider.

CachedNetworkImage (imageUrl: "http://via.placeholder.com/350x150", placeholder: (context, url) => new CircularProgressIndicator (), errorWidget: (context, url, error) => новый значок (Icons.error),), enter code here

0 голосов
/ 17 декабря 2018

Вы можете использовать Flutter Multipart , что-то вроде этого

 // open a bytestream
    var stream = new http.ByteStream(DelegatingStream.typed(_image.openRead()));
    // get file length
    var length = await _image.length();
    // string to uri
    var uri = Uri.parse(apiUrl);
    // create multipart request
    var request = new http.MultipartRequest("POST", uri);
    NetworkUtils.addAuthHeaders(request);
    // multipart that takes file
    var multipartFile = new http.MultipartFile('file', stream, length,
        filename: basename(_image.path),
        contentType: new MediaType("image", "jpg"));
    // add file to multipart
    request.files.add(multipartFile);
    request.fields.addAll(body);
    // send
    var response = await request.send();
    print(response.statusCode);
    // listen for response
    response.stream.transform(utf8.decoder).listen((value) {
      print(value);
    });
  }
...