Skip to content
Snippets Groups Projects
minio_uploader.dart 3.31 KiB
import 'dart:async';
import 'dart:convert';

import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:minio/minio.dart';
import 'package:minio/models.dart';
import 'package:minio/src/utils.dart';

class MinioUploader implements StreamConsumer<List<int>> {
  MinioUploader(
    this.minio,
    this.client,
    this.bucket,
    this.object,
    this.partSize,
    this.metadata,
  );

  final Minio minio;
  final MinioClient client;
  final String bucket;
  final String object;
  final int partSize;
  final Map<String, String> metadata;

  var partNumber = 1;
  String etag;
  List<CompletedPart> parts = [];
  Map<int, Part> oldParts;
  String uploadId;

  @override
  Future addStream(Stream<List<int>> stream) async {
    await for (var chunk in stream) {
      List<int> md5digest;
      final headers = <String, String>{};
      headers.addAll(metadata);
      headers['Content-Length'] = chunk.length.toString();
      if (!client.enableSHA256) {
        md5digest = md5.convert(chunk).bytes;
        headers['Content-MD5'] = base64.encode(md5digest);
      }

      if (this.partNumber == 1 && chunk.length < partSize) {
        this.etag = await upload(chunk, headers, null);
        return;
      }

      if (uploadId == null) {
        await initMultipartUpload();
      }

      final partNumber = this.partNumber++;

      if (oldParts != null) {
        final oldPart = oldParts[partNumber];
        if (oldPart != null) {
          md5digest ??= md5.convert(chunk).bytes;
          if (hex.encode(md5digest) == oldPart.eTag) {
            final part = CompletedPart(oldPart.eTag, partNumber);
            parts.add(part);
            continue;
          }
        }
      }

      final queries = {
        'partNumber': partNumber,
        'uploadId': uploadId,