github.com/minio/minio-go/v6@v6.0.57/api-put-object-copy.go (about) 1 /* 2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage 3 * Copyright 2017, 2018 MinIO, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package minio 19 20 import ( 21 "context" 22 "io" 23 "io/ioutil" 24 "net/http" 25 "time" 26 27 "github.com/minio/minio-go/v6/pkg/encrypt" 28 "github.com/minio/minio-go/v6/pkg/s3utils" 29 ) 30 31 // CopyObject - copy a source object into a new object 32 func (c Client) CopyObject(dst DestinationInfo, src SourceInfo) error { 33 return c.CopyObjectWithProgress(dst, src, nil) 34 } 35 36 // CopyObjectWithProgress - copy a source object into a new object, optionally takes 37 // progress bar input to notify current progress. 38 func (c Client) CopyObjectWithProgress(dst DestinationInfo, src SourceInfo, progress io.Reader) error { 39 header := make(http.Header) 40 for k, v := range src.Headers { 41 header[k] = v 42 } 43 44 if dst.opts.ReplaceTags && len(dst.opts.UserTags) != 0 { 45 header.Set(amzTaggingHeaderDirective, "REPLACE") 46 header.Set(amzTaggingHeader, s3utils.TagEncode(dst.opts.UserTags)) 47 } 48 49 if dst.opts.LegalHold != LegalHoldStatus("") { 50 header.Set(amzLegalHoldHeader, dst.opts.LegalHold.String()) 51 } 52 53 if dst.opts.Mode != RetentionMode("") && !dst.opts.RetainUntilDate.IsZero() { 54 header.Set(amzLockMode, dst.opts.Mode.String()) 55 header.Set(amzLockRetainUntil, dst.opts.RetainUntilDate.Format(time.RFC3339)) 56 } 57 58 var err error 59 var size int64 60 // If progress bar is specified, size should be requested as well initiate a StatObject request. 61 if progress != nil { 62 size, _, _, err = src.getProps(c) 63 if err != nil { 64 return err 65 } 66 } 67 68 if src.encryption != nil { 69 encrypt.SSECopy(src.encryption).Marshal(header) 70 } 71 72 if dst.opts.Encryption != nil { 73 dst.opts.Encryption.Marshal(header) 74 } 75 for k, v := range dst.getUserMetaHeadersMap(true) { 76 header.Set(k, v) 77 } 78 79 resp, err := c.executeMethod(context.Background(), "PUT", requestMetadata{ 80 bucketName: dst.bucket, 81 objectName: dst.object, 82 customHeader: header, 83 }) 84 if err != nil { 85 return err 86 } 87 defer closeResponse(resp) 88 89 if resp.StatusCode != http.StatusOK { 90 return httpRespToErrorResponse(resp, dst.bucket, dst.object) 91 } 92 93 // Update the progress properly after successful copy. 94 if progress != nil { 95 io.CopyN(ioutil.Discard, progress, size) 96 } 97 98 return nil 99 }