github.com/chnsz/golangsdk@v0.0.0-20240506093406-85a3fbfa605b/openstack/obs/client_part.go (about)

     1  // Copyright 2019 Huawei Technologies Co.,Ltd.
     2  // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
     3  // this file except in compliance with the License.  You may obtain a copy of the
     4  // License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software distributed
     9  // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    10  // CONDITIONS OF ANY KIND, either express or implied.  See the License for the
    11  // specific language governing permissions and limitations under the License.
    12  
    13  package obs
    14  
    15  import (
    16  	"errors"
    17  	"io"
    18  	"os"
    19  	"sort"
    20  	"strings"
    21  )
    22  
    23  // ListMultipartUploads lists the multipart uploads.
    24  //
    25  // You can use this API to list the multipart uploads that are initialized but not combined or aborted in a specified bucket.
    26  func (obsClient ObsClient) ListMultipartUploads(input *ListMultipartUploadsInput, extensions ...extensionOptions) (output *ListMultipartUploadsOutput, err error) {
    27  	if input == nil {
    28  		return nil, errors.New("ListMultipartUploadsInput is nil")
    29  	}
    30  	output = &ListMultipartUploadsOutput{}
    31  	err = obsClient.doActionWithBucket("ListMultipartUploads", HTTP_GET, input.Bucket, input, output, extensions)
    32  	if err != nil {
    33  		output = nil
    34  	} else if output.EncodingType == "url" {
    35  		err = decodeListMultipartUploadsOutput(output)
    36  		if err != nil {
    37  			doLog(LEVEL_ERROR, "Failed to get ListMultipartUploadsOutput with error: %v.", err)
    38  			output = nil
    39  		}
    40  	}
    41  	return
    42  }
    43  
    44  // AbortMultipartUpload aborts a multipart upload in a specified bucket by using the multipart upload ID.
    45  func (obsClient ObsClient) AbortMultipartUpload(input *AbortMultipartUploadInput, extensions ...extensionOptions) (output *BaseModel, err error) {
    46  	if input == nil {
    47  		return nil, errors.New("AbortMultipartUploadInput is nil")
    48  	}
    49  	if input.UploadId == "" {
    50  		return nil, errors.New("UploadId is empty")
    51  	}
    52  	output = &BaseModel{}
    53  	err = obsClient.doActionWithBucketAndKey("AbortMultipartUpload", HTTP_DELETE, input.Bucket, input.Key, input, output, extensions)
    54  	if err != nil {
    55  		output = nil
    56  	}
    57  	return
    58  }
    59  
    60  // InitiateMultipartUpload initializes a multipart upload.
    61  func (obsClient ObsClient) InitiateMultipartUpload(input *InitiateMultipartUploadInput, extensions ...extensionOptions) (output *InitiateMultipartUploadOutput, err error) {
    62  	if input == nil {
    63  		return nil, errors.New("InitiateMultipartUploadInput is nil")
    64  	}
    65  
    66  	if input.ContentType == "" && input.Key != "" {
    67  		if contentType, ok := mimeTypes[strings.ToLower(input.Key[strings.LastIndex(input.Key, ".")+1:])]; ok {
    68  			input.ContentType = contentType
    69  		}
    70  	}
    71  
    72  	output = &InitiateMultipartUploadOutput{}
    73  	err = obsClient.doActionWithBucketAndKey("InitiateMultipartUpload", HTTP_POST, input.Bucket, input.Key, input, output, extensions)
    74  	if err != nil {
    75  		output = nil
    76  	} else {
    77  		ParseInitiateMultipartUploadOutput(output)
    78  		if output.EncodingType == "url" {
    79  			err = decodeInitiateMultipartUploadOutput(output)
    80  			if err != nil {
    81  				doLog(LEVEL_ERROR, "Failed to get InitiateMultipartUploadOutput with error: %v.", err)
    82  				output = nil
    83  			}
    84  		}
    85  	}
    86  	return
    87  }
    88  
    89  // UploadPart uploads a part to a specified bucket by using a specified multipart upload ID.
    90  //
    91  // After a multipart upload is initialized, you can use this API to upload a part to a specified bucket
    92  // by using the multipart upload ID. Except for the last uploaded part whose size ranges from 0 to 5 GB,
    93  // sizes of the other parts range from 100 KB to 5 GB. The upload part ID ranges from 1 to 10000.
    94  func (obsClient ObsClient) UploadPart(_input *UploadPartInput, extensions ...extensionOptions) (output *UploadPartOutput, err error) {
    95  	if _input == nil {
    96  		return nil, errors.New("UploadPartInput is nil")
    97  	}
    98  
    99  	if _input.UploadId == "" {
   100  		return nil, errors.New("UploadId is empty")
   101  	}
   102  
   103  	input := &UploadPartInput{}
   104  	input.Bucket = _input.Bucket
   105  	input.Key = _input.Key
   106  	input.PartNumber = _input.PartNumber
   107  	input.UploadId = _input.UploadId
   108  	input.ContentMD5 = _input.ContentMD5
   109  	input.SourceFile = _input.SourceFile
   110  	input.Offset = _input.Offset
   111  	input.PartSize = _input.PartSize
   112  	input.SseHeader = _input.SseHeader
   113  	input.Body = _input.Body
   114  
   115  	output = &UploadPartOutput{}
   116  	var repeatable bool
   117  	if input.Body != nil {
   118  		if _, ok := input.Body.(*strings.Reader); ok {
   119  			repeatable = true
   120  		}
   121  		if _, ok := input.Body.(*readerWrapper); !ok && input.PartSize > 0 {
   122  			input.Body = &readerWrapper{reader: input.Body, totalCount: input.PartSize}
   123  		}
   124  	} else if sourceFile := strings.TrimSpace(input.SourceFile); sourceFile != "" {
   125  		fd, _err := os.Open(sourceFile)
   126  		if _err != nil {
   127  			err = _err
   128  			return nil, err
   129  		}
   130  		defer func() {
   131  			errMsg := fd.Close()
   132  			if errMsg != nil {
   133  				doLog(LEVEL_WARN, "Failed to close file with reason: %v", errMsg)
   134  			}
   135  		}()
   136  
   137  		stat, _err := fd.Stat()
   138  		if _err != nil {
   139  			err = _err
   140  			return nil, err
   141  		}
   142  		fileSize := stat.Size()
   143  		fileReaderWrapper := &fileReaderWrapper{filePath: sourceFile}
   144  		fileReaderWrapper.reader = fd
   145  
   146  		if input.Offset < 0 || input.Offset > fileSize {
   147  			input.Offset = 0
   148  		}
   149  
   150  		if input.PartSize <= 0 || input.PartSize > (fileSize-input.Offset) {
   151  			input.PartSize = fileSize - input.Offset
   152  		}
   153  		fileReaderWrapper.totalCount = input.PartSize
   154  		if _, err = fd.Seek(input.Offset, io.SeekStart); err != nil {
   155  			return nil, err
   156  		}
   157  		input.Body = fileReaderWrapper
   158  		repeatable = true
   159  	}
   160  	if repeatable {
   161  		err = obsClient.doActionWithBucketAndKey("UploadPart", HTTP_PUT, input.Bucket, input.Key, input, output, extensions)
   162  	} else {
   163  		err = obsClient.doActionWithBucketAndKeyUnRepeatable("UploadPart", HTTP_PUT, input.Bucket, input.Key, input, output, extensions)
   164  	}
   165  	if err != nil {
   166  		output = nil
   167  	} else {
   168  		ParseUploadPartOutput(output)
   169  		output.PartNumber = input.PartNumber
   170  	}
   171  	return
   172  }
   173  
   174  // CompleteMultipartUpload combines the uploaded parts in a specified bucket by using the multipart upload ID.
   175  func (obsClient ObsClient) CompleteMultipartUpload(input *CompleteMultipartUploadInput, extensions ...extensionOptions) (output *CompleteMultipartUploadOutput, err error) {
   176  	if input == nil {
   177  		return nil, errors.New("CompleteMultipartUploadInput is nil")
   178  	}
   179  
   180  	if input.UploadId == "" {
   181  		return nil, errors.New("UploadId is empty")
   182  	}
   183  
   184  	var parts partSlice = input.Parts
   185  	sort.Sort(parts)
   186  
   187  	output = &CompleteMultipartUploadOutput{}
   188  	err = obsClient.doActionWithBucketAndKey("CompleteMultipartUpload", HTTP_POST, input.Bucket, input.Key, input, output, extensions)
   189  	if err != nil {
   190  		output = nil
   191  	} else {
   192  		ParseCompleteMultipartUploadOutput(output)
   193  		if output.EncodingType == "url" {
   194  			err = decodeCompleteMultipartUploadOutput(output)
   195  			if err != nil {
   196  				doLog(LEVEL_ERROR, "Failed to get CompleteMultipartUploadOutput with error: %v.", err)
   197  				output = nil
   198  			}
   199  		}
   200  	}
   201  	return
   202  }
   203  
   204  // ListParts lists the uploaded parts in a bucket by using the multipart upload ID.
   205  func (obsClient ObsClient) ListParts(input *ListPartsInput, extensions ...extensionOptions) (output *ListPartsOutput, err error) {
   206  	if input == nil {
   207  		return nil, errors.New("ListPartsInput is nil")
   208  	}
   209  	if input.UploadId == "" {
   210  		return nil, errors.New("UploadId is empty")
   211  	}
   212  	output = &ListPartsOutput{}
   213  	err = obsClient.doActionWithBucketAndKey("ListParts", HTTP_GET, input.Bucket, input.Key, input, output, extensions)
   214  	if err != nil {
   215  		output = nil
   216  	} else if output.EncodingType == "url" {
   217  		err = decodeListPartsOutput(output)
   218  		if err != nil {
   219  			doLog(LEVEL_ERROR, "Failed to get ListPartsOutput with error: %v.", err)
   220  			output = nil
   221  		}
   222  	}
   223  	return
   224  }
   225  
   226  // CopyPart copy a part to a specified bucket by using a specified multipart upload ID.
   227  //
   228  // After a multipart upload is initialized, you can use this API to copy a part to a specified bucket by using the multipart upload ID.
   229  func (obsClient ObsClient) CopyPart(input *CopyPartInput, extensions ...extensionOptions) (output *CopyPartOutput, err error) {
   230  	if input == nil {
   231  		return nil, errors.New("CopyPartInput is nil")
   232  	}
   233  	if input.UploadId == "" {
   234  		return nil, errors.New("UploadId is empty")
   235  	}
   236  	if strings.TrimSpace(input.CopySourceBucket) == "" {
   237  		return nil, errors.New("Source bucket is empty")
   238  	}
   239  	if strings.TrimSpace(input.CopySourceKey) == "" {
   240  		return nil, errors.New("Source key is empty")
   241  	}
   242  
   243  	output = &CopyPartOutput{}
   244  	err = obsClient.doActionWithBucketAndKey("CopyPart", HTTP_PUT, input.Bucket, input.Key, input, output, extensions)
   245  	if err != nil {
   246  		output = nil
   247  	} else {
   248  		ParseCopyPartOutput(output)
   249  		output.PartNumber = input.PartNumber
   250  	}
   251  	return
   252  }