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  }