Flutter AWS S3集成插件roflit_s3的使用

Flutter AWS S3 集成插件 roflit_s3 的使用

安装

pubspec.yaml 文件中添加依赖:

dependencies:
  roflit_s3: <latest_version>

导入

在 Dart 文件中导入插件:

import 'package:roflit_s3/roflit_s3.dart';

入门指南

要使用 Roflit S3,你需要完成三个步骤:

步骤 1: 创建一个 RoflitS3 实例

// 如何获取存储账户参数可以参见你使用的云服务的文档和管理控制台。
final storage = RoflitS3(
  accessKeyId: cloudStorageServiceAccount.keyIdentifier,
  secretAccessKey: cloudStorageServiceAccount.secretKey,
  host: cloudStorage.host,
  region: cloudStorage.region,
);
// 如果你是第一次使用该云服务,你可能还需要:
// 1. 在云存储上创建一个帐户;
// 2. 分配角色(访问权限);
// 3. 为它创建一个静态密钥并保存其详细信息(accessKeyId 和 secretAccessKey)。

步骤 2: 形成请求数据

// 生成查询数据以从云中选择数据。
final requestBucketsData = storage.buckets.get();
// 删除云中的存储桶。
final requestBucketObjectsData = storage.buckets.getObjects(
  bucketName: 'bucketName',
);

步骤 3: 发送请求数据到请求客户端

Response<dynamic>? response;
switch(requestData.typeRequest){
  case RequestType.get:
    final response = await _dio.get<dynamic>(
      requestData.url.toString(),
      options: Options(headers: requestData.headers),
    ).timeout(const Duration(seconds: 10));
  case RequestType.delete:
    final response = await _dio.delete<dynamic>(
      requestData.url.toString(),
      options: Options(headers: requestData.headers),
    );
  ...
}

要读取存储桶和对象数据,你需要解析 XML 或将 XML 转换为 JSON。更多详情请参见示例。

读取/下载对象

有以下两种方法来读取或下载私有存储中的对象:

方法 1: 签名请求

// 生成签名请求数据。
final object = storage.objects.get(
  bucketName: 'bucketName',
  objectKey: 'objectKey',
);
// 使用 url 和 headers 在你的小部件中。
Image.network(
  object.url.toString(),
  headers: object.headers,
)

方法 2: 签名链接

// 生成签名链接数据。
final object = storage.objects.get(
  bucketName: 'bucketName',
  objectKey: 'objectKey',
  useSignedUrl: true,
);
// 只使用 url。
Image.network(
  object.url.toString(),
)

示例代码

以下是完整的示例代码:

import 'dart:convert';
import 'dart:developer';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:roflit_s3/roflit_s3.dart';
import 'package:roflit_s3_example/entity/object.dart';
import 'package:roflit_s3_example/entity/result.dart';
import 'package:xml2json/xml2json.dart';

import 'entity/bucket.dart';
import 'util/extension_converter.dart';

void main() async {
  const bucketName = 'my-bucket';
  const objectName = 'my-object';
  const host = 'storage.yandexcloud.net';

  final serializer = Serializer(host: host);
  final operations = Operations();

  // keyIdentifier 和 secretKey 是在云存储控制台为服务帐户创建的密钥的属性。
  final storage = RoflitS3(
    accessKeyId: '************',
    secretAccessKey: '****************',
    host: host,
    region: 'ru-central1',
  );

  // 创建存储桶
  final createBucketResponse = await operations.createBucket(
    storage,
    bucketName: bucketName,
  );

  if (!createBucketResponse.isSuccess) {
    debugPrint('Error: ${createBucketResponse.message}');
    return;
  }

  // 获取存储桶
  final getBucketsResponse = await operations.getBuckets(storage);

  if (!getBucketsResponse.isSuccess) {
    debugPrint('Error: ${getBucketsResponse.message}');
    return;
  }
  final buckets = serializer.buckets(getBucketsResponse.success);
  debugPrint('Buckets $buckets');

  // 将文件(对象)上传到存储桶。
  final uploadObjectResponse = await operations.uploadObject(
    storage,
    bucketName: bucketName,
    objectName: objectName,
  );

  if (!uploadObjectResponse.isSuccess) {
    debugPrint('Error: ${uploadObjectResponse.message}');
    return;
  }

  // 获取对象
  final getObjectsResponse = await operations.getObjects(
    storage,
    bucketName: bucketName,
  );

  if (!getObjectsResponse.isSuccess) {
    debugPrint('Error: ${getObjectsResponse.message}');
    return;
  }
  final objects = serializer.objects(getObjectsResponse.success);
  debugPrint('Objects $objects');

  // 删除对象
  final deleteObjectsResponse = await operations.deleteObject(
    storage,
    bucketName: bucketName,
    objectName: bucketName,
  );
  if (!deleteObjectsResponse.isSuccess) {
    debugPrint('Error: ${deleteObjectsResponse.message}');
    return;
  }

  // 删除存储桶
  final deleteBucketResponse = await operations.deleteBucket(
    storage,
    bucketName: bucketName,
  );
  if (!deleteBucketResponse.isSuccess) {
    debugPrint('Error: ${deleteBucketResponse.message}');
    return;
  }
}

class Operations {
  final client = DioClient();

  Future<Result> createBucket(RoflitS3 storage, {required String bucketName}) async {
    final dto = storage.buckets.create(
      bucketName: bucketName,
      headers: {'X-Amz-Acl': 'public-read'}, // or 'bucket-owner-full-control'
    );

    return client.send(dto);
  }

  Future<Result> getBuckets(RoflitS3 storage) async {
    final dto = storage.buckets.get();
    return client.send(dto);
  }

  Future<Result> uploadObject(
    RoflitS3 storage, {
    required String bucketName,
    required String objectName,
  }) async {
    final file = File('your/local-path/file.ext');

    final dto = storage.objects.upload(
      bucketName: bucketName,
      objectKey: objectName,
      headers: ObjectUploadHadersParameters(bodyBytes: file.readAsBytesSync()),
      body: file.readAsBytesSync(),
    );

    return client.send(dto);
  }

  Future<Result> getObjects(
    RoflitS3 storage, {
    required String bucketName,
  }) async {
    final dto = storage.buckets.getObjects(bucketName: bucketName);
    return client.send(dto);
  }

  Future<Result> deleteObject(
    RoflitS3 storage, {
    required String bucketName,
    required String objectName,
  }) async {
    final dto = storage.objects.delete(bucketName: bucketName, objectKey: objectName);
    return client.send(dto);
  }

  Future<Result> deleteBucket(
    RoflitS3 storage, {
    required String bucketName,
  }) async {
    final dto = storage.buckets.delete(bucketName: bucketName);
    return client.send(dto);
  }
}

class DioClient {
  final _dio = Dio();

  Future<Result> send(
    RoflitRequest client,
  ) async {
    Response<dynamic>? response;
    try {
      switch (client.typeRequest) {
        case RequestType.get:
          response = await _dio
              .get<dynamic>(
                client.url.toString(),
                options: Options(
                  headers: client.headers,
                ),
              )
              .timeout(const Duration(seconds: 10));

        case RequestType.put:
          response = await _dio.put(
            client.url.toString(),
            options: Options(headers: client.headers),
            data: client.body,
            onSendProgress: (count, total) {
              log('S3 PUT $count / $total');
            },
          );
        case RequestType.delete:
          response = await _dio.delete(
            client.url.toString(),
            options: Options(
              headers: client.headers,
            ),
          );
        case RequestType.post:
          response = await _dio.post(
            client.url.toString(),
            options: Options(
              headers: client.headers,
            ),
            data: client.body,
          );
      }

      final statusCode = response.statusCode ?? 400;

      if (statusCode < 200 || statusCode >= 300) {
        return Result.failuer(
          statusCode: response.statusCode,
          message: response.statusMessage,
          success: response.data,
        );
      } else {
        return Result.success(
          statusCode: response.statusCode,
          success: response.data,
        );
      }
    } catch (e, s) {
      return Result.failuer(
        statusCode: 400,
        message: 'Runtime error $e $s',
      );
    }
  }
}

class Serializer {
  final String host;

  Serializer({required this.host});

  final _parser = Xml2Json();

  List<BucketEntity> buckets(Object? value) {
    try {
      _parser.parse(value as String);
      final json = jsonDecode(_parser.toParker());
      final document = json['ListAllMyBucketsResult'];
      final buckets = document['Buckets']['Bucket'];

      if (buckets is Map) {
        return [
          BucketEntity(
            bucket: buckets['Name'],
            creationDate: buckets['CreationDate'],
          )
        ];
      }

      final newBuckets = List.generate(buckets?.length ?? 0, (index) {
        final bucket = buckets![index];
        return BucketEntity(
          bucket: bucket['Name'],
          creationDate: bucket['CreationDate'],
        );
      });

      return newBuckets;
    } catch (e) {
      return [];
    }
  }

  List<ObjectEntity> objects(Object? value) {
    try {
      _parser.parse(value as String);
      final json = jsonDecode(_parser.toParker());
      final document = json['ListBucketResult'];

      final bucket = document['Name'];
      final objects = document['Contents'];

      if (objects is Map) {
        return [
          ObjectEntity(
            objectKey: objects['Key'],
            bucket: bucket,
            type: FormatConverter.converter(objects['Key']),
            nesting: FormatConverter.nesting(objects['Key']),
            remotePath: '$host/$bucket/${objects['Key']}',
            size: int.tryParse(objects['Size']) ?? 0,
            lastModified: objects['LastModified'],
          )
        ];
      }

      final newObjects = List.generate(objects?.length ?? 0, (index) {
        final object = objects![index];

        return ObjectEntity(
          objectKey: object['Key'],
          bucket: bucket,
          type: FormatConverter.converter(object['Key']),
          nesting: FormatConverter.nesting(object['Key']),
          remotePath: '$host/$bucket/${object['Key']}',
          size: int.tryParse(object['Size']) ?? 0,
          lastModified: object['LastModified'],
        );
      });

      return newObjects;
    } catch (e) {
      return [];
    }
  }
}

更多关于Flutter AWS S3集成插件roflit_s3的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter AWS S3集成插件roflit_s3的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中集成并使用roflit_s3插件来与AWS S3进行交互的代码示例。这个插件可以帮助你轻松地在Flutter应用中上传和下载文件到AWS S3。

首先,你需要在你的Flutter项目中添加roflit_s3依赖。打开你的pubspec.yaml文件并添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  roflit_s3: ^最新版本号  # 请替换为实际可用的最新版本号

然后运行flutter pub get来安装依赖。

接下来,你需要在AWS上配置你的S3存储桶,并确保你已经创建了具有适当权限的IAM用户。你需要获取这个用户的Access Key IDSecret Access Key,以及存储桶的名称和区域。

在你的Flutter项目中,你需要初始化S3Client实例,并使用它来上传或下载文件。以下是一个简单的示例,展示了如何上传文件到S3:

import 'package:flutter/material.dart';
import 'package:roflit_s3/roflit_s3.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter AWS S3 Example'),
        ),
        body: Center(
          child: UploadButton(),
        ),
      ),
    );
  }
}

class UploadButton extends StatefulWidget {
  @override
  _UploadButtonState createState() => _UploadButtonState();
}

class _UploadButtonState extends State<UploadButton> {
  final String accessKeyId = '你的AccessKeyId';
  final String secretAccessKey = '你的SecretAccessKey';
  final String bucketName = '你的存储桶名称';
  final String region = '你的区域';  // 例如 'us-west-2'

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        try {
          // 初始化S3Client
          final s3Client = S3Client(
            accessKeyId: accessKeyId,
            secretAccessKey: secretAccessKey,
            region: region,
          );

          // 选择文件(这里以本地文件为例,实际应用中可能需要使用文件选择器)
          final file = File('/path/to/your/local/file.txt');

          // 上传文件
          await s3Client.uploadFile(
            bucketName: bucketName,
            key: 'uploaded/file.txt',  // 上传到S3的路径和文件名
            filePath: file.path,
          );

          // 显示成功信息
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('文件上传成功!')),
          );
        } catch (e) {
          // 显示错误信息
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('文件上传失败: ${e.message}')),
          );
        }
      },
      child: Text('上传文件'),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮,用于将本地文件上传到AWS S3。你需要替换accessKeyIdsecretAccessKeybucketNameregion为你的实际值。

如果你还需要下载文件,可以使用S3ClientdownloadFile方法。以下是一个简单的下载文件示例:

// ...

ElevatedButton(
  onPressed: () async {
    try {
      // 初始化S3Client(与之前相同)
      final s3Client = S3Client(
        accessKeyId: accessKeyId,
        secretAccessKey: secretAccessKey,
        region: region,
      );

      // 指定下载文件的S3路径和本地保存路径
      final s3Key = 'uploaded/file.txt';
      final localPath = '/path/to/save/downloaded/file.txt';

      // 下载文件
      await s3Client.downloadFile(
        bucketName: bucketName,
        key: s3Key,
        filePath: localPath,
      );

      // 显示成功信息
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('文件下载成功!')),
      );
    } catch (e) {
      // 显示错误信息
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('文件下载失败: ${e.message}')),
      );
    }
  },
  child: Text('下载文件'),
),
// ...

这个示例展示了如何下载之前上传到S3的文件,并将其保存到本地路径。

请确保在实际应用中处理敏感信息(如AWS凭证)时采取适当的安全措施,例如使用环境变量或安全的密钥管理服务。

回到顶部