diff --git a/README.md b/README.md
index b2705839f13afb560b244a3d94ed6a2e3bf5f860..840beb24b89a30bf1c5d8dcdd5f88a3a27383f5d 100644
--- a/README.md
+++ b/README.md
@@ -10,9 +10,9 @@ Created from templates made available by Stagehand under a BSD-style
 | `makeBucket`           	| `getObject`            	| presignedUrl         	| getBucketNotification                   	|
 | `listBuckets`          	| `getPartialObject`     	| presignedGetObject   	| setBucketNotification                   	|
 | `bucketExists`         	| fGetObject             	| presignedPutObject   	| removeAllBucketNotification             	|
-| `removeBucket`         	| putObject              	| presignedPostPolicy  	| getBucketPolicy                         	|
+| `removeBucket`         	| `putObject`            	| presignedPostPolicy  	| getBucketPolicy                         	|
 | `listObjects`          	| fPutObject             	|                      	| setBucketPolicy                         	|
-| listObjectsV2         	| copyObject             	|                      	| listenBucketNotification                	|
+| listObjectsV2         	| `copyObject`           	|                      	| listenBucketNotification                	|
 | `listIncompleteUploads`	| statObject             	|                      	|                                         	|
 |                       	| removeObject           	|                      	|                                         	|
 |                       	| removeObjects          	|                      	|                                         	|
diff --git a/example/minio_example.dart b/example/minio_example.dart
index fc7faf2ebb304f377d34ff6c4de6a0201d8e90f1..e2b9f26e50d4fca45662f61494637710932a3f80 100644
--- a/example/minio_example.dart
+++ b/example/minio_example.dart
@@ -39,8 +39,15 @@ void main() async {
   // await File('sys8_captcha.png').openWrite().addStream(object);
 
   final file = File('example/teaweb.png');
+  final object = 'teaweb.png';
   final size = await file.length();
-  final etag =
-      await minio.putObject(bucket, 'teaweb.png', file.openRead(), size);
+  final etag = await minio.putObject(bucket, object, file.openRead(), size);
   print(etag);
+
+  final copyResult = await minio.copyObject(
+    bucket,
+    '$object.copy',
+    '$bucket/$object',
+  );
+  print(copyResult.eTag);
 }
diff --git a/lib/src/minio.dart b/lib/src/minio.dart
index e57a8ec2a7f40a5620242177f6fc17261e1a3f40..4f260f53e9722ae4a94b065b2420f8f142e84141 100644
--- a/lib/src/minio.dart
+++ b/lib/src/minio.dart
@@ -307,6 +307,50 @@ class Minio {
     return etag;
   }
 
+  Future<CopyObjectResult> copyObject(
+    String bucket,
+    String object,
+    String srcObject, [
+    CopyConditions conditions,
+  ]) async {
+    MinioInvalidBucketNameError.check(bucket);
+    MinioInvalidObjectNameError.check(object);
+    MinioInvalidObjectNameError.check(srcObject);
+
+    final headers = <String, String>{};
+    headers['x-amz-copy-source'] = srcObject;
+
+    if (conditions != null) {
+      if (conditions.modified != null) {
+        headers['x-amz-copy-source-if-modified-since'] = conditions.modified;
+      }
+      if (conditions.unmodified != null) {
+        headers['x-amz-copy-source-if-unmodified-since'] =
+            conditions.unmodified;
+      }
+      if (conditions.matchETag != null) {
+        headers['x-amz-copy-source-if-match'] = conditions.matchETag;
+      }
+      if (conditions.matchETagExcept != null) {
+        headers['x-amz-copy-source-if-none-match'] = conditions.matchETagExcept;
+      }
+    }
+
+    final resp = await _client.request(
+      method: 'PUT',
+      bucket: bucket,
+      object: object,
+      headers: headers,
+    );
+
+    validate(resp);
+
+    final node = xml.parse(resp.body);
+    final result =  CopyObjectResult.fromXml(node.rootElement);
+    result.eTag = trimDoubleQuote(result.eTag);
+    return result;
+  }
+
   Future<String> findUploadID(String bucket, String object) async {
     MinioInvalidBucketNameError.check(bucket);
     MinioInvalidObjectNameError.check(object);
diff --git a/lib/src/minio_models.dart b/lib/src/minio_models.dart
index 4b2957e09ab919cf089de5eb15075d68bbd49f02..4c3f08b1e217bebba6e0110068a2308d62db8ce9 100644
--- a/lib/src/minio_models.dart
+++ b/lib/src/minio_models.dart
@@ -65,7 +65,30 @@ class IncompleteUpload {
     this.upload,
     this.size,
   });
-  
+
   final MultipartUpload upload;
   final int size;
 }
+
+class CopyConditions {
+  String modified;
+  String unmodified;
+  String matchETag;
+  String matchETagExcept;
+
+  void setModified(DateTime date) {
+    modified = date.toUtc().toIso8601String();
+  }
+
+  void setUnmodified(DateTime date) {
+    unmodified = date.toUtc().toIso8601String();
+  }
+
+  void setMatchETag(String etag) {
+    matchETag = etag;
+  }
+
+  void setMatchETagExcept(String etag) {
+    matchETagExcept = etag;
+  }
+}
diff --git a/lib/src/minio_uploader.dart b/lib/src/minio_uploader.dart
index f8d115a9699b1259b15e24d613840fa9939b2953..2487c20f7d319fc652f617d13ec664daa26330c3 100644
--- a/lib/src/minio_uploader.dart
+++ b/lib/src/minio_uploader.dart
@@ -5,6 +5,7 @@ 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(
@@ -110,7 +111,7 @@ class MinioUploader implements StreamConsumer<List<int>> {
 
     var etag = resp.headers['etag'];
     if (etag != null) {
-      etag = etag.replaceAll(RegExp('^"'), '').replaceAll(RegExp(r'"$'), '');
+      etag = trimDoubleQuote(etag);
     }
 
     return etag;
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 774a07d2ad9f3aa07ef5657dd301612874ba73e8..920c02683e526aaeacde0f107fa26ca5454f5d23 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -65,3 +65,7 @@ class BlockStream extends StreamTransformerBase<List<int>, List<int>> {
     }
   }
 }
+
+String trimDoubleQuote(String str) {
+  return str.replaceAll(RegExp('^"'), '').replaceAll(RegExp(r'"$'), '');
+}
\ No newline at end of file