// Copy object from one bucket to another public async static Task Run(MinioClient minio, string fromBucketName = "from-bucket-name", string fromObjectName = "from-object-name", string destBucketName = "dest-bucket", string destObjectName = "to-object-name") { try { Console.WriteLine("Running example for API: CopyObjectAsync"); // Optionally pass copy conditions to replace metadata on destination object with custom metadata CopyConditions copyCond = new CopyConditions(); copyCond.SetReplaceMetadataDirective(); // set custom metadata var metadata = new Dictionary <string, string> { { "Content-Type", "application/css" }, { "X-Amz-Meta-Mynewkey", "my-new-value" } }; await minio.CopyObjectAsync(fromBucketName, fromObjectName, destBucketName, destObjectName, copyConditions : copyCond, metadata : metadata); Console.WriteLine("Copied object {0} from bucket {1} to bucket {2}", fromObjectName, fromBucketName, destBucketName); Console.WriteLine(); } catch (Exception e) { Console.WriteLine("[Bucket] Exception: {0}", e); } }
/// <summary> /// Make a multi part copy upload for objects larger than 5GB or if CopyCondition specifies a byte range. /// </summary> /// <param name="bucketName"> source bucket name</param> /// <param name="objectName"> source object name</param> /// <param name="destBucketName"> destination bucket name</param> /// <param name="destObjectName"> destiantion object name</param> /// <param name="copyConditions"> copyconditions </param> /// <param name="copySize"> size of copy upload</param> /// <param name="cancellationToken"> optional cancellation token</param> /// <returns></returns> private async Task MultipartCopyUploadAsync(string bucketName, string objectName, string destBucketName, string destObjectName, CopyConditions copyConditions, long copySize, CancellationToken cancellationToken) { // For all sizes greater than 5GB or if Copy byte range specified in conditions and byte range larger // than minimum part size (5 MB) do multipart. dynamic multiPartInfo = utils.CalculateMultiPartSize(copySize); double partSize = multiPartInfo.partSize; double partCount = multiPartInfo.partCount; double lastPartSize = multiPartInfo.lastPartSize; Part[] totalParts = new Part[(int)partCount]; // No need to resume upload since this is a server side copy. Just initiate a new upload. string uploadId = await this.NewMultipartUploadAsync(destBucketName, destObjectName, null, cancellationToken); // Upload each part double expectedReadSize = partSize; int partNumber; for (partNumber = 1; partNumber <= partCount; partNumber++) { CopyConditions partCondition = copyConditions.Clone(); partCondition.byteRangeStart = (long)partSize * (partNumber - 1) + partCondition.byteRangeStart; if (partNumber < partCount) { partCondition.byteRangeEnd = partCondition.byteRangeStart + (long)partSize - 1; } else { partCondition.byteRangeEnd = partCondition.byteRangeStart + (long)lastPartSize - 1; } var resource = ""; if (!string.IsNullOrEmpty(uploadId) && partNumber > 0) { resource += "?uploadId=" + uploadId + "&partNumber=" + partNumber; } Dictionary <string, string> customHeader = new Dictionary <string, string>(); customHeader.Add("x-amz-copy-source-range", "bytes=" + partCondition.byteRangeStart.ToString() + "-" + partCondition.byteRangeEnd.ToString()); CopyPartResult cpPartResult = (CopyPartResult)await this.CopyObjectRequestAsync(bucketName, objectName, destBucketName, destObjectName, copyConditions, customHeader, resource, cancellationToken, typeof(CopyPartResult)); totalParts[partNumber - 1] = new Part() { PartNumber = partNumber, ETag = cpPartResult.ETag, size = (long)expectedReadSize }; } Dictionary <int, string> etags = new Dictionary <int, string>(); for (partNumber = 1; partNumber <= partCount; partNumber++) { etags[partNumber] = totalParts[partNumber - 1].ETag; } // Complete multi part upload await this.CompleteMultipartUploadAsync(destBucketName, destObjectName, uploadId, etags, cancellationToken); }
private async static Task CopyObject_Test3(MinioClient minio) { Console.Out.WriteLine("Test3: CopyObjectsAsync"); // Test CopyConditions where matching ETag is found string bucketName = GetRandomName(15); string objectName = GetRandomName(10); string destBucketName = GetRandomName(15); string destObjectName = GetRandomName(10); string fileName = CreateFile(1 * MB); await Setup_Test(minio, bucketName); await Setup_Test(minio, destBucketName); await minio.PutObjectAsync(bucketName, objectName, fileName); ObjectStat stats = await minio.StatObjectAsync(bucketName, objectName); CopyConditions conditions = new CopyConditions(); conditions.SetMatchETag(stats.ETag); try { await minio.CopyObjectAsync(bucketName, objectName, destBucketName, destObjectName, conditions); } catch (MinioException) { Assert.Fail(); } string outFileName = "outFileName"; ObjectStat dstats = await minio.StatObjectAsync(destBucketName, destObjectName); Assert.IsNotNull(dstats); Assert.AreEqual(dstats.ETag, stats.ETag); Assert.AreEqual(dstats.ObjectName, destObjectName); await minio.GetObjectAsync(destBucketName, destObjectName, outFileName); File.Delete(outFileName); await minio.RemoveObjectAsync(bucketName, objectName); await minio.RemoveObjectAsync(destBucketName, destObjectName); await TearDown(minio, bucketName); await TearDown(minio, destBucketName); File.Delete(fileName); Console.Out.WriteLine("Test3: CopyObjectsAsync Complete"); }
private async static Task CopyObject_Test5(MinioClient minio) { // Test if multi-part copy upload for large files works as expected. Console.Out.WriteLine("Test5: CopyObjectsAsync"); string bucketName = GetRandomName(15); string objectName = GetRandomName(10); string destBucketName = GetRandomName(15); string fileName = CreateFile(7 * MB); await Setup_Test(minio, bucketName); await Setup_Test(minio, destBucketName); await minio.PutObjectAsync(bucketName, objectName, fileName); CopyConditions conditions = new CopyConditions(); conditions.SetByteRange(1024, 6291456); // omit dest object name. await minio.CopyObjectAsync(bucketName, objectName, destBucketName, copyConditions : conditions); string outFileName = "outFileName"; await minio.GetObjectAsync(bucketName, objectName, outFileName); File.Delete(outFileName); ObjectStat stats = await minio.StatObjectAsync(destBucketName, objectName); Assert.IsNotNull(stats); Assert.AreEqual(stats.ObjectName, objectName); Assert.AreEqual(stats.Size, 6291456 - 1024 + 1); await minio.RemoveObjectAsync(bucketName, objectName); await minio.RemoveObjectAsync(destBucketName, objectName); await TearDown(minio, bucketName); await TearDown(minio, destBucketName); File.Delete(fileName); Console.Out.WriteLine("Test4: CopyObjectsAsync Complete"); }
private async static Task CopyObject_Test4(MinioClient minio) { // Test if objectName is defaulted to source objectName Console.Out.WriteLine("Test4: CopyObjectsAsync"); string bucketName = GetRandomName(15); string objectName = GetRandomName(10); string destBucketName = GetRandomName(15); string fileName = CreateFile(1 * MB); await Setup_Test(minio, bucketName); await Setup_Test(minio, destBucketName); await minio.PutObjectAsync(bucketName, objectName, fileName); CopyConditions conditions = new CopyConditions(); conditions.SetMatchETag("TestETag"); // omit dest bucket name. await minio.CopyObjectAsync(bucketName, objectName, destBucketName); string outFileName = "outFileName"; await minio.GetObjectAsync(bucketName, objectName, outFileName); File.Delete(outFileName); ObjectStat stats = await minio.StatObjectAsync(destBucketName, objectName); Assert.IsNotNull(stats); Assert.AreEqual(stats.ObjectName, objectName); await minio.RemoveObjectAsync(bucketName, objectName); await minio.RemoveObjectAsync(destBucketName, objectName); await TearDown(minio, bucketName); await TearDown(minio, destBucketName); File.Delete(fileName); Console.Out.WriteLine("Test4: CopyObjectsAsync Complete"); }
// Copy object from one bucket to another public static async Task Run(MinioClient minio, string fromBucketName = "from-bucket-name", string fromObjectName = "from-object-name", string destBucketName = "dest-bucket", string destObjectName = "to-object-name") { try { Console.WriteLine("Running example for API: CopyObjectAsync"); // Optionally pass copy conditions to replace metadata on destination object with custom metadata var copyCond = new CopyConditions(); copyCond.SetReplaceMetadataDirective(); // set custom metadata var metadata = new Dictionary <string, string> { { "Content-Type", "application/css" }, { "Mynewkey", "my-new-value" } }; var copySourceObjectArgs = new CopySourceObjectArgs() .WithBucket(fromBucketName) .WithObject(fromObjectName) .WithCopyConditions(copyCond); var copyObjectArgs = new CopyObjectArgs() .WithBucket(destBucketName) .WithObject(destObjectName) .WithHeaders(metadata) .WithCopyObjectSource(copySourceObjectArgs); await minio.CopyObjectAsync(copyObjectArgs); Console.WriteLine( $"Copied object {fromObjectName} from bucket {fromBucketName} to bucket {destBucketName}"); Console.WriteLine(); } catch (Exception e) { Console.WriteLine($"[Bucket] Exception: {e}"); } }
private async static Task CopyObject_Test2(MinioClient minio) { Console.Out.WriteLine("Test2: CopyObjectsAsync"); // Test CopyConditions where matching ETag is not found string bucketName = GetRandomName(15); string objectName = GetRandomName(10); string destBucketName = GetRandomName(15); string destObjectName = GetRandomName(10); string fileName = CreateFile(1 * MB); await Setup_Test(minio, bucketName); await Setup_Test(minio, destBucketName); await minio.PutObjectAsync(bucketName, objectName, fileName); CopyConditions conditions = new CopyConditions(); conditions.SetMatchETag("TestETag"); try { await minio.CopyObjectAsync(bucketName, objectName, destBucketName, destObjectName, conditions); } catch (MinioException ex) { Assert.AreEqual(ex.Message, "Minio API responded with message=At least one of the pre-conditions you specified did not hold"); } await minio.RemoveObjectAsync(bucketName, objectName); await TearDown(minio, bucketName); await TearDown(minio, destBucketName); File.Delete(fileName); Console.Out.WriteLine("Test2: CopyObjectsAsync Complete"); }
/// <summary> /// Create the copy request,execute it and /// </summary> /// <param name="bucketName"> Bucket name where the object to be copied exists.</param> /// <param name="objectName">Object name source to be copied.</param> /// <param name="destBucketName">Bucket name where the object will be copied to.</param> /// <param name="destObjectName">Object name to be created, if not provided uses source object name as destination object name.</param> /// <param name="copyConditions">optionally can take a key value CopyConditions as well for conditionally attempting copyObject.</param> /// <param name="customHeaders">optional custom header to specify byte range</param> /// <param name="resource"> optional string to specify upload id and part number </param> /// <param name="type"> type of XML serialization to be applied on the server response</param> /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param> /// <returns></returns> private async Task <object> CopyObjectRequestAsync(string bucketName, string objectName, string destBucketName, string destObjectName, CopyConditions copyConditions, Dictionary <string, string> customHeaders, string resource, CancellationToken cancellationToken, Type type) { // Escape source object path. string sourceObjectPath = bucketName + "/" + utils.UrlEncode(objectName); // Destination object name is optional, if empty default to source object name. if (destObjectName == null) { destObjectName = objectName; } var path = destBucketName + "/" + utils.UrlEncode(destObjectName); var request = await this.CreateRequest(Method.PUT, destBucketName, objectName : destObjectName, resourcePath : resource, headerMap : customHeaders ); // Set the object source request.AddHeader("x-amz-copy-source", sourceObjectPath); // If no conditions available, skip addition else add the conditions to the header if (copyConditions != null) { foreach (var item in copyConditions.GetConditions()) { request.AddHeader(item.Key, item.Value); } } var response = await this.ExecuteTaskAsync(this.NoErrorHandlers, request, cancellationToken); // Just read the result and parse content. var contentBytes = System.Text.Encoding.UTF8.GetBytes(response.Content); object copyResult = null; using (var stream = new MemoryStream(contentBytes)) { if (type == typeof(CopyObjectResult)) { copyResult = (CopyObjectResult)(new XmlSerializer(typeof(CopyObjectResult)).Deserialize(stream)); } if (type == typeof(CopyPartResult)) { copyResult = (CopyPartResult)(new XmlSerializer(typeof(CopyPartResult)).Deserialize(stream)); } } return(copyResult); }
/// <summary> /// Copy a source object into a new destination object. /// </summary> /// <param name="bucketName"> Bucket name where the object to be copied exists.</param> /// <param name="objectName">Object name source to be copied.</param> /// <param name="destBucketName">Bucket name where the object will be copied to.</param> /// <param name="destObjectName">Object name to be created, if not provided uses source object name as destination object name.</param> /// <param name="copyConditions">optionally can take a key value CopyConditions as well for conditionally attempting copyObject.</param> /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param> /// <returns></returns> public async Task CopyObjectAsync(string bucketName, string objectName, string destBucketName, string destObjectName = null, CopyConditions copyConditions = null, CancellationToken cancellationToken = default(CancellationToken)) { if (bucketName == null) { throw new ArgumentException("Source bucket name cannot be empty"); } if (objectName == null) { throw new ArgumentException("Source object name cannot be empty"); } if (destBucketName == null) { throw new ArgumentException("Destination bucket name cannot be empty"); } // Escape source object path. string sourceObjectPath = bucketName + "/" + utils.UrlEncode(objectName); // Destination object name is optional, if empty default to source object name. if (destObjectName == null) { destObjectName = objectName; } // Get Stats on the source object ObjectStat srcStats = await this.StatObjectAsync(bucketName, objectName, cancellationToken); long srcByteRangeSize = 0L; if (copyConditions != null) { srcByteRangeSize = copyConditions.GetByteRange(); } long copySize = (srcByteRangeSize == 0) ? srcStats.Size : srcByteRangeSize; if ((srcByteRangeSize > srcStats.Size) || ((srcByteRangeSize > 0) && (copyConditions.byteRangeEnd >= srcStats.Size))) { throw new ArgumentException("Specified byte range (" + copyConditions.byteRangeStart.ToString() + "-" + copyConditions.byteRangeEnd.ToString() + ") does not fit within source object (size=" + srcStats.Size.ToString() + ")"); } if ((copySize > Constants.MaxSingleCopyObjectSize) || (srcByteRangeSize > 0 && (srcByteRangeSize != srcStats.Size))) { await MultipartCopyUploadAsync(bucketName, objectName, destBucketName, destObjectName, copyConditions, copySize, cancellationToken); } else { await this.CopyObjectRequestAsync(bucketName, objectName, destBucketName, destObjectName, copyConditions, null, null, cancellationToken, typeof(CopyObjectResult)); } }
//Copies content from objectName to destObjectName. public Task CopyObjectFromToAsync(string bucketName, string objectName, string destBucketName, string destObjectName = null, CopyConditions copyConditions = null, Dictionary <string, string> metadata = null, ServerSideEncryption sseSrc = null, ServerSideEncryption sseDest = null, CancellationToken cancellationToken = default(CancellationToken)) { try { /* * CopyConditions copyConditions = new CopyConditions(); * copyConditions.setMatchETagNone("TestETag"); * ServerSideEncryption sseSrc, sseDst; */ // Uncomment to specify source and destination Server-side encryption options /* * Aes aesEncryption = Aes.Create(); * aesEncryption.KeySize = 256; * aesEncryption.GenerateKey(); * sseSrc = new SSEC(aesEncryption.Key); * sseDst = new SSES3(); */ var taskCopyObj = minio.CopyObjectAsync(bucketName, objectName, destBucketName, destObjectName, copyConditions, metadata, sseSrc, sseDest, cancellationToken); return(taskCopyObj); } catch (MinioException e) { throw; } }