diff --git a/example/minio_example.dart b/example/minio_example.dart
index 4b19f389c58d233fed11a440735e982b9ad24105..fc7faf2ebb304f377d34ff6c4de6a0201d8e90f1 100644
--- a/example/minio_example.dart
+++ b/example/minio_example.dart
@@ -11,8 +11,17 @@ void main() async {
     secretKey: 'zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG',
   );
 
+  final bucket = '00test';
+
+  if (!await minio.bucketExists(bucket)) {
+    await minio.makeBucket(bucket);
+    print('bucket $bucket created');
+  } else {
+    print('bucket $bucket already exists');
+  }
+
   // print(await minio.bucketExists('02test'));
-  // await minio.makeBucket('05test');
+  // await minio.makeBucket('00test');
   // await minio.removeBucket('05test');
   // print(await minio.getBucketRegion('00test'));
   // print(await minio.getBucketRegion('00test'));
@@ -28,4 +37,10 @@ void main() async {
 
   // final object = await minio.getObject('00test', 'sys8_captcha.png');
   // await File('sys8_captcha.png').openWrite().addStream(object);
+
+  final file = File('example/teaweb.png');
+  final size = await file.length();
+  final etag =
+      await minio.putObject(bucket, 'teaweb.png', file.openRead(), size);
+  print(etag);
 }
diff --git a/example/teaweb.png b/example/teaweb.png
new file mode 100644
index 0000000000000000000000000000000000000000..84746b3b671c92a99bfe0bb17c9abd2a66b24ac6
Binary files /dev/null and b/example/teaweb.png differ
diff --git a/lib/src/minio.dart b/lib/src/minio.dart
index 752f456f58251bf027920eba47faf91393f7fc74..e57a8ec2a7f40a5620242177f6fc17261e1a3f40 100644
--- a/lib/src/minio.dart
+++ b/lib/src/minio.dart
@@ -156,8 +156,8 @@ class MinioClient {
       if (object != null) path = '/${bucket}/${object}';
     }
 
-    final resourcePart = resource != null ? '$resource&' : '';
-    final queryPart = encodeQueries(queries);
+    final resourcePart = resource == null ? '' : '$resource&';
+    final queryPart = queries == null ? '' : encodeQueries(queries);
     final query = resourcePart + queryPart;
 
     return Uri(
@@ -179,7 +179,12 @@ class MinioClient {
     for (var header in request.headers.entries) {
       buffer.writeln('${header.key}: ${header.value}');
     }
-    buffer.writeln(request.body);
+
+    if (request.body is List<int>) {
+      buffer.writeln('List<int> of size ${request.body.length}');
+    } else {
+      buffer.writeln(request.body);
+    }
 
     print(buffer.toString());
   }
@@ -237,11 +242,14 @@ class Minio {
 
   Future<bool> bucketExists(String bucket) async {
     MinioInvalidBucketNameError.check(bucket);
-    final resp = await _client.request(method: 'HEAD', bucket: bucket);
-    if (resp.statusCode != 200 && resp.statusCode != 404) {
-      throw MinioS3Error('bucketExists failed.');
+    try {
+      await _client.request(method: 'HEAD', bucket: bucket);
+    } on MinioS3Error catch (e) {
+      final code = e.error.code;
+      if (code == 'NoSuchBucket' || code == 'NotFound') return false;
+      rethrow;
     }
-    return resp.statusCode == 200;
+    return true;
   }
 
   int calculatePartSize(int size) {
@@ -349,7 +357,7 @@ class Minio {
     final node = xml.parse(resp.body);
     final location = node.findAllElements('LocationConstraint').first.text;
 
-    _regionMap[bucket] = location;
+    _regionMap[bucket] = location ?? 'us-east-1';
     return location;
   }
 
@@ -645,7 +653,7 @@ class Minio {
     Stream<List<int>> data,
     int size, {
     Map<String, String> metadata,
-  }) {
+  }) async {
     MinioInvalidBucketNameError.check(bucket);
     MinioInvalidObjectNameError.check(object);
 
@@ -653,15 +661,21 @@ class Minio {
     assert(size >= 0 || size == null);
 
     metadata = prependXAMZMeta(metadata ?? {});
-    // Stream.
 
     size ??= maxObjectSize;
     size = calculatePartSize(size);
 
     final chunker = BlockStream(size);
-    final uploader =
-        MinioUploader(this, _client, bucket, object, size, metadata);
-    return data.transform(chunker).pipe(uploader);
+    final uploader = MinioUploader(
+      this,
+      _client,
+      bucket,
+      object,
+      size,
+      metadata,
+    );
+    final etag = await data.transform(chunker).pipe(uploader);
+    return etag.toString();
   }
 
   Future<void> removeBucket(String bucket) async {
diff --git a/lib/src/minio_uploader.dart b/lib/src/minio_uploader.dart
index 38d0e856f2957119770db295529cfe14528397a0..f8d115a9699b1259b15e24d613840fa9939b2953 100644
--- a/lib/src/minio_uploader.dart
+++ b/lib/src/minio_uploader.dart
@@ -42,7 +42,8 @@ class MinioUploader implements StreamConsumer<List<int>> {
       }
 
       if (this.partNumber == 1 && chunk.length < partSize) {
-        return uploadInOneGo(chunk, headers);
+        this.etag = await upload(chunk, headers, null);
+        return;
       }
 
       if (uploadId == null) {
@@ -68,20 +69,7 @@ class MinioUploader implements StreamConsumer<List<int>> {
         'uploadId': uploadId,
       };
 
-      final resp = await client.request(
-        method: 'PUT',
-        queries: queries,
-        headers: headers,
-        bucket: bucket,
-        object: object,
-      );
-
-      validate(resp);
-
-      var etag = resp.headers['etag'];
-      if (etag != null) {
-        etag = etag.replaceAll(RegExp('^"'), '').replaceAll(RegExp(r'"$'), '');
-      }
+      final etag = await upload(chunk, headers, queries);
       final part = CompletedPart(etag, partNumber);
       parts.add(part);
     }
@@ -89,10 +77,7 @@ class MinioUploader implements StreamConsumer<List<int>> {
 
   @override
   Future<String> close() async {
-    if (uploadId == null) {
-      return etag;
-    }
-
+    if (uploadId == null) return etag;
     return minio.completeMultipartUpload(bucket, object, uploadId, parts);
   }
 
@@ -107,11 +92,15 @@ class MinioUploader implements StreamConsumer<List<int>> {
     return headers;
   }
 
-  Future<void> uploadInOneGo(
-      List<int> chunk, Map<String, String> headers) async {
+  Future<String> upload(
+    List<int> chunk,
+    Map<String, String> headers,
+    Map<String, String> queries,
+  ) async {
     final resp = await client.request(
       method: 'PUT',
       headers: headers,
+      queries: queries,
       bucket: bucket,
       object: object,
       payload: chunk,
@@ -119,10 +108,12 @@ class MinioUploader implements StreamConsumer<List<int>> {
 
     validate(resp);
 
-    etag = resp.headers['etag'];
+    var etag = resp.headers['etag'];
     if (etag != null) {
       etag = etag.replaceAll(RegExp('^"'), '').replaceAll(RegExp(r'"$'), '');
     }
+
+    return etag;
   }
 
   Future<void> initMultipartUpload() async {
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 36ecc57afa90737c1bba8a10d423c154b94b3826..774a07d2ad9f3aa07ef5657dd301612874ba73e8 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -7,8 +7,16 @@ import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
 import 'package:xml/xml.dart';
 
-String sha256Hex(String data) {
-  return hex.encode(sha256.convert(utf8.encode(data)).bytes);
+String sha256Hex(Object data) {
+  if (data is String) {
+    data = utf8.encode(data);
+  } else if (data is List<int>) {
+    data = data;
+  } else {
+    throw ArgumentError('unsupported data type: ${data.runtimeType}');
+  }
+
+  return hex.encode(sha256.convert(data).bytes);
 }
 
 XmlElement getNodeProp(XmlElement xml, String name) {