上载和在Flutter中从AWS S3提取媒体文件 [英] Upload & fetch media files from AWS S3 in Flutter

查看:564
本文介绍了上载和在Flutter中从AWS S3提取媒体文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的flutter应用程序正在使用Firebase作为后端,但我需要在s3存储桶中存储媒体文件(照片和视频).任务是将从图像选择器检索到的媒体上传到s3& amp;中.取回网址,然后可以将其作为字符串存储在我的Firebase数据库中.

My flutter app is using firebase as a backend but I need to store media files (photos & videos) in my s3 bucket. The mission is to upload the media retrieved from the image picker into s3 & get back the url, which can then be stored as a string in my firebase database.

问题是dart 2缺少aws库或api.我在pub中发现3个,但其中2个与dart 2& 1个正在开发中.有没有人用飞镖2在颤抖中实现这一点?欢迎任何建议.谢谢.

The problem is a scarcity of aws libraries or api for dart 2. I found 3 in pub, but 2 of them were incompatible with dart 2 & 1 was under development. Has anyone implemented this in flutter using dart 2? Any suggestions are welcome. Thank you.

我找到的包是(pub.dartlang.org):aws_client,aws_interop,amazon_s3

The packages I found were (pub.dartlang.org) : aws_client, aws_interop, amazon_s3

推荐答案

有几种方法可以做到这一点.一种方法是签署您的请求并使用签名V4 POST您的文件到S3

There's a few ways to do this. One way is to sign your request with Signature V4 and POST your file to S3.

首先,创建一个策略助手:

First, create a policy helper:

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上传:

Then, sign your request with your policy helper and upload via 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之类的服务,建议您获取一个临时访问密钥和秘密密钥.在此处中找到了使用临时访问的示例.

Please note that this method requires you to provide your Access Key and Secret Key. If you use a service like Cognito, it is recommended to get a temporary Access Key and Secret Key. Examples using temporary access found here.

免责声明:我是签名V4软件包的原始作者..

Disclaimer: I am the original author of the Signature V4 package.

这篇关于上载和在Flutter中从AWS S3提取媒体文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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