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 }