api-put-object-copy.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. package s3cli
  18. import (
  19. "context"
  20. "io"
  21. "io/ioutil"
  22. "net/http"
  23. "github.com/minio/minio-go/v6/pkg/encrypt"
  24. )
  25. // CopyObject - copy a source object into a new object
  26. func (c Client) CopyObject(dst DestinationInfo, src SourceInfo) error {
  27. return c.CopyObjectWithProgress(dst, src, nil)
  28. }
  29. // CopyObjectWithProgress - copy a source object into a new object, optionally takes
  30. // progress bar input to notify current progress.
  31. func (c Client) CopyObjectWithProgress(dst DestinationInfo, src SourceInfo, progress io.Reader) error {
  32. header := make(http.Header)
  33. for k, v := range src.Headers {
  34. header[k] = v
  35. }
  36. var err error
  37. var size int64
  38. // If progress bar is specified, size should be requested as well initiate a StatObject request.
  39. if progress != nil {
  40. size, _, _, err = src.getProps(c)
  41. if err != nil {
  42. return err
  43. }
  44. }
  45. if src.encryption != nil {
  46. encrypt.SSECopy(src.encryption).Marshal(header)
  47. }
  48. if dst.encryption != nil {
  49. dst.encryption.Marshal(header)
  50. }
  51. for k, v := range dst.getUserMetaHeadersMap(true) {
  52. header.Set(k, v)
  53. }
  54. resp, err := c.executeMethod(context.Background(), "PUT", requestMetadata{
  55. bucketName: dst.bucket,
  56. objectName: dst.object,
  57. customHeader: header,
  58. })
  59. if err != nil {
  60. return err
  61. }
  62. defer closeResponse(resp)
  63. if resp.StatusCode != http.StatusOK {
  64. return httpRespToErrorResponse(resp, dst.bucket, dst.object)
  65. }
  66. // Update the progress properly after successful copy.
  67. if progress != nil {
  68. io.CopyN(ioutil.Discard, progress, size)
  69. }
  70. return nil
  71. }