Flutter对象存储插件minio的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter对象存储插件minio的使用

MinIO Dart 简介

MinIO Dart 是一个非官方的 MinIO 客户端 SDK,它提供了简单的 API 来访问任何兼容 Amazon S3 的对象存储服务器。该 SDK 支持多种操作,包括桶(bucket)管理、对象管理、预签名 URL 创建等。

GitHub Workflow Status Pub Version Buy Me a Coffee

API 概览

Bucket operations Object operations Presigned operations Bucket Policy & Notification operations
makeBucket getObject presignedUrl getBucketNotification
listBuckets getPartialObject presignedGetObject setBucketNotification
bucketExists fGetObject presignedPutObject removeAllBucketNotification
removeBucket putObject presignedPostPolicy listenBucketNotification
listObjects fPutObject getBucketPolicy
listObjectsV2 copyObject setBucketPolicy
listIncompleteUploads statObject
listAllObjects removeObject
listAllObjectsV2 removeObjects
removeIncompleteUpload

使用方法

初始化 MinIO 客户端

final minio = Minio(
  endPoint: 'play.min.io',
  accessKey: 'Q3AM3UQ867SPQQA43P2F',
  secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
);

对于 AWS S3 和其他兼容 S3 的服务提供商,可以类似地初始化客户端:

// AWS S3
final minio = Minio(
  endPoint: 's3.amazonaws.com',
  accessKey: 'YOUR-ACCESSKEYID',
  secretKey: 'YOUR-SECRETACCESSKEY',
);

// Filebase
final minio = Minio(
  endPoint: 's3.filebase.com',
  accessKey: 'YOUR-ACCESSKEYID',
  secretKey: 'YOUR-SECRETACCESSKEY',
  useSSL: true,
);

文件上传

import 'package:minio/io.dart';
import 'package:minio/minio.dart';

void main() async {
  final minio = Minio(
    endPoint: 'play.min.io',
    accessKey: 'Q3AM3UQ867SPQQA43P2F',
    secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
  );

  await minio.fPutObject('mybucket', 'myobject', 'path/to/file');
}

带进度的文件上传

import 'package:minio/minio.dart';

void main() async {
  final minio = Minio(
    endPoint: 'play.min.io',
    accessKey: 'Q3AM3UQ867SPQQA43P2F',
    secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
  );

  await minio.putObject(
    'mybucket',
    'myobject',
    Stream<Uint8List>.value(Uint8List(1024)),
    onProgress: (bytes) => print('$bytes uploaded'),
  );
}

获取对象

import 'dart:io';
import 'package:minio/minio.dart';

void main() async {
  final minio = Minio(
    endPoint: 's3.amazonaws.com',
    accessKey: 'YOUR-ACCESSKEYID',
    secretKey: 'YOUR-SECRETACCESSKEY',
  );

  final stream = await minio.getObject('BUCKET-NAME', 'OBJECT-NAME');

  // 获取对象长度
  print(stream.contentLength);

  // 将对象数据流写入文件
  await stream.pipe(File('output.txt').openWrite());
}

示例代码

以下是一个完整的示例代码,展示了如何创建桶、上传文件、获取预签名 URL、复制对象、列出对象、获取对象元数据、删除对象和删除桶等操作。

import 'package:minio/io.dart';
import 'package:minio/minio.dart';

void main() async {
  final minio = Minio(
    endPoint: 'play.min.io',
    accessKey: 'Q3AM3UQ867SPQQA43P2F',
    secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
    useSSL: true,
  );

  final bucket = '00test';
  final object = 'custed.png';
  final copy1 = 'custed.copy1.png';
  final copy2 = 'custed.copy2.png';

  if (!await minio.bucketExists(bucket)) {
    await minio.makeBucket(bucket);
    print('bucket $bucket created');
  } else {
    print('bucket $bucket already exists');
  }

  final poller = minio.listenBucketNotification(
    bucket,
    events: [
      's3:ObjectCreated:*',
    ],
  );
  poller.stream.listen((event) {
    print('--- event: ${event['eventName']}');
  });

  final region = await minio.getBucketRegion('00test');
  print('--- object region:');
  print(region);

  final etag = await minio.fPutObject(bucket, object, 'example/$object');
  print('--- etag:');
  print(etag);

  final url = await minio.presignedGetObject(bucket, object, expires: 1000);
  print('--- presigned url:');
  print(url);

  final copyResult1 = await minio.copyObject(bucket, copy1, '$bucket/$object');
  final copyResult2 = await minio.copyObject(bucket, copy2, '$bucket/$object');
  print('--- copy1 etag:');
  print(copyResult1.eTag);
  print('--- copy2 etag:');
  print(copyResult2.eTag);

  await minio.fGetObject(bucket, object, 'example/$copy1');
  print('--- copy1 downloaded');

  await minio.listObjects(bucket).forEach((chunk) {
    print('--- objects:');
    for (var o in chunk.objects) {
      print(o.key);
    }
  });

  await minio.listObjectsV2(bucket).forEach((chunk) {
    print('--- objects(v2):');
    for (var o in chunk.objects) {
      print(o.key);
    }
  });

  final stat = await minio.statObject(bucket, object);
  print('--- object stat:');
  print(stat.etag);
  print(stat.size);
  print(stat.lastModified);
  print(stat.metaData);

  await minio.removeObject(bucket, object);
  print('--- object removed');

  await minio.removeObjects(bucket, [copy1, copy2]);
  print('--- copy1, copy2 removed');

  await minio.removeBucket(bucket);
  print('--- bucket removed');

  poller.stop();
}

特性和问题

请在 issue tracker 上提交功能请求和错误报告。欢迎贡献代码。

许可证

MIT License - 详情


希望这些信息对你有帮助!如果你有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter对象存储插件minio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter对象存储插件minio的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用MinIO对象存储插件的示例代码。这个示例将展示如何连接到MinIO服务器、创建存储桶、上传和下载文件。

首先,你需要在Flutter项目中添加minio依赖。由于Flutter本身没有官方的MinIO插件,我们将使用Dart的HTTP客户端库与MinIO的REST API进行交互。以下步骤假设你已经有一个运行中的MinIO服务器,并且你有访问密钥和密钥对。

  1. 添加依赖: 在pubspec.yaml文件中添加http依赖。

    dependencies:
      flutter:
        sdk: flutter
      http: ^0.13.3  # 请检查最新版本
    
  2. 连接到MinIO服务器

    下面是一个示例代码,展示如何连接到MinIO服务器、创建存储桶、上传和下载文件。

    import 'dart:convert';
    import 'dart:io';
    import 'package:http/http.dart' as http;
    
    class MinioClient {
      final String endpoint;
      final int port;
      final String accessKey;
      final String secretKey;
    
      MinioClient({
        required this.endpoint,
        required this.port,
        required this.accessKey,
        required this.secretKey,
      });
    
      String get authorizationHeader {
        var date = DateTime.now().toUtc().toHttpDate();
        var stringToSign = 'PUT\n\n\n${date}\n/your-bucket-name\n';
        var secretAccessKey = secretKey;
        var hmacSha256 = Hmac(sha256, utf8.encode(secretAccessKey))
            .convert(utf8.encode(date));
        var signature = base64.encode(hmacSha256.bytes);
        var authorization = 'AWS4-HMAC-SHA256 Credential=${accessKey}/${_getDateStamp()}/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=$signature';
        return authorization;
      }
    
      String _getDateStamp() {
        var now = DateTime.now().toUtc();
        return '${now.year}${now.month < 10 ? '0' : ''}${now.month}${now.day < 10 ? '0' : ''}${now.day}';
      }
    
      Future<void> createBucket(String bucketName) async {
        var url = Uri.parse('http://$endpoint:$port/$bucketName');
        var response = await http.put(
          url,
          headers: {
            'Authorization': authorizationHeader,
            'x-amz-content-sha256': 'UNSIGNED-PAYLOAD',
            'x-amz-date': DateTime.now().toUtc().toHttpDate(),
            'Host': '$endpoint:$port',
          },
        );
    
        if (response.statusCode != 200) {
          throw Exception('Failed to create bucket: ${response.statusCode}');
        }
      }
    
      Future<void> uploadFile(String bucketName, File file, String objectName) async {
        var multipartFile = await http.MultipartFile.fromPath(
          'file',
          file.path,
          contentType: MediaType('application', 'octet-stream'),
        );
    
        var request = http.MultipartRequest('POST', Uri.parse('http://$endpoint:$port/$bucketName/$objectName'));
        request.headers.addAll({
          'Authorization': authorizationHeader,
          'x-amz-content-sha256': 'UNSIGNED-PAYLOAD',
          'x-amz-date': DateTime.now().toUtc().toHttpDate(),
          'Host': '$endpoint:$port',
        });
        request.files.add(multipartFile);
    
        var response = await request.send();
    
        if (response.statusCode != 200) {
          throw Exception('Failed to upload file: ${response.statusCode}');
        }
      }
    
      Future<void> downloadFile(String bucketName, String objectName, File outputFile) async {
        var url = Uri.parse('http://$endpoint:$port/$bucketName/$objectName');
        var response = await http.get(
          url,
          headers: {
            'Authorization': authorizationHeader,
            'x-amz-date': DateTime.now().toUtc().toHttpDate(),
            'Host': '$endpoint:$port',
          },
        );
    
        if (response.statusCode != 200) {
          throw Exception('Failed to download file: ${response.statusCode}');
        }
    
        await outputFile.writeAsBytes(response.bodyBytes);
      }
    }
    
    void main() async {
      var minioClient = MinioClient(
        endpoint: 'your-minio-server-endpoint',
        port: 9000,
        accessKey: 'your-access-key',
        secretKey: 'your-secret-key',
      );
    
      try {
        // 创建存储桶
        await minioClient.createBucket('your-bucket-name');
        print('Bucket created successfully');
    
        // 上传文件
        var file = File('path/to/your/file.txt');
        await minioClient.uploadFile('your-bucket-name', file, 'file.txt');
        print('File uploaded successfully');
    
        // 下载文件
        var outputFile = File('path/to/downloaded/file.txt');
        await minioClient.downloadFile('your-bucket-name', 'file.txt', outputFile);
        print('File downloaded successfully');
      } catch (e) {
        print('Error: $e');
      }
    }
    

注意事项

  • 上面的代码示例仅用于说明如何与MinIO进行交互,并不包含所有错误处理和边缘情况。
  • authorizationHeader 的生成逻辑只是一个示例,实际的签名过程会更复杂,并且需要符合AWS V4签名规范。
  • 你可以使用MinIO官方提供的SDK(如Python SDK)生成签名,然后在Flutter中直接使用这些签名。
  • 请确保在生产环境中使用HTTPS来保护你的通信。

希望这个示例代码对你有所帮助!

回到顶部