github.com/chnsz/golangsdk@v0.0.0-20240506093406-85a3fbfa605b/openstack/obs/client_object.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 "fmt" 18 "io" 19 "os" 20 "strings" 21 ) 22 23 // ListObjects lists objects in a bucket. 24 // 25 // You can use this API to list objects in a bucket. By default, a maximum of 1000 objects are listed. 26 func (obsClient ObsClient) ListObjects(input *ListObjectsInput, extensions ...extensionOptions) (output *ListObjectsOutput, err error) { 27 if input == nil { 28 return nil, errors.New("ListObjectsInput is nil") 29 } 30 output = &ListObjectsOutput{} 31 err = obsClient.doActionWithBucket("ListObjects", HTTP_GET, input.Bucket, input, output, extensions) 32 if err != nil { 33 output = nil 34 } else { 35 if location, ok := output.ResponseHeaders[HEADER_BUCKET_REGION]; ok { 36 output.Location = location[0] 37 } 38 if output.EncodingType == "url" { 39 err = decodeListObjectsOutput(output) 40 if err != nil { 41 doLog(LEVEL_ERROR, "Failed to get ListObjectsOutput with error: %v.", err) 42 output = nil 43 } 44 } 45 } 46 return 47 } 48 49 // ListVersions lists versioning objects in a bucket. 50 // 51 // You can use this API to list versioning objects in a bucket. By default, a maximum of 1000 versioning objects are listed. 52 func (obsClient ObsClient) ListVersions(input *ListVersionsInput, extensions ...extensionOptions) (output *ListVersionsOutput, err error) { 53 if input == nil { 54 return nil, errors.New("ListVersionsInput is nil") 55 } 56 output = &ListVersionsOutput{} 57 err = obsClient.doActionWithBucket("ListVersions", HTTP_GET, input.Bucket, input, output, extensions) 58 if err != nil { 59 output = nil 60 } else { 61 if location, ok := output.ResponseHeaders[HEADER_BUCKET_REGION]; ok { 62 output.Location = location[0] 63 } 64 if output.EncodingType == "url" { 65 err = decodeListVersionsOutput(output) 66 if err != nil { 67 doLog(LEVEL_ERROR, "Failed to get ListVersionsOutput with error: %v.", err) 68 output = nil 69 } 70 } 71 } 72 return 73 } 74 75 // HeadObject checks whether an object exists. 76 // 77 // You can use this API to check whether an object exists. 78 func (obsClient ObsClient) HeadObject(input *HeadObjectInput, extensions ...extensionOptions) (output *BaseModel, err error) { 79 if input == nil { 80 return nil, errors.New("HeadObjectInput is nil") 81 } 82 output = &BaseModel{} 83 err = obsClient.doActionWithBucketAndKey("HeadObject", HTTP_HEAD, input.Bucket, input.Key, input, output, extensions) 84 if err != nil { 85 output = nil 86 } 87 return 88 } 89 90 // SetObjectMetadata sets object metadata. 91 func (obsClient ObsClient) SetObjectMetadata(input *SetObjectMetadataInput, extensions ...extensionOptions) (output *SetObjectMetadataOutput, err error) { 92 output = &SetObjectMetadataOutput{} 93 err = obsClient.doActionWithBucketAndKey("SetObjectMetadata", HTTP_PUT, input.Bucket, input.Key, input, output, extensions) 94 if err != nil { 95 output = nil 96 } else { 97 ParseSetObjectMetadataOutput(output) 98 } 99 return 100 } 101 102 // DeleteObject deletes an object. 103 // 104 // You can use this API to delete an object from a specified bucket. 105 func (obsClient ObsClient) DeleteObject(input *DeleteObjectInput, extensions ...extensionOptions) (output *DeleteObjectOutput, err error) { 106 if input == nil { 107 return nil, errors.New("DeleteObjectInput is nil") 108 } 109 output = &DeleteObjectOutput{} 110 err = obsClient.doActionWithBucketAndKey("DeleteObject", HTTP_DELETE, input.Bucket, input.Key, input, output, extensions) 111 if err != nil { 112 output = nil 113 } else { 114 ParseDeleteObjectOutput(output) 115 } 116 return 117 } 118 119 // DeleteObjects deletes objects in a batch. 120 // 121 // You can use this API to batch delete objects from a specified bucket. 122 func (obsClient ObsClient) DeleteObjects(input *DeleteObjectsInput, extensions ...extensionOptions) (output *DeleteObjectsOutput, err error) { 123 if input == nil { 124 return nil, errors.New("DeleteObjectsInput is nil") 125 } 126 output = &DeleteObjectsOutput{} 127 err = obsClient.doActionWithBucket("DeleteObjects", HTTP_POST, input.Bucket, input, output, extensions) 128 if err != nil { 129 output = nil 130 } else if output.EncodingType == "url" { 131 err = decodeDeleteObjectsOutput(output) 132 if err != nil { 133 doLog(LEVEL_ERROR, "Failed to get DeleteObjectsOutput with error: %v.", err) 134 output = nil 135 } 136 } 137 return 138 } 139 140 // SetObjectAcl sets ACL for an object. 141 // 142 // You can use this API to set the ACL for an object in a specified bucket. 143 func (obsClient ObsClient) SetObjectAcl(input *SetObjectAclInput, extensions ...extensionOptions) (output *BaseModel, err error) { 144 if input == nil { 145 return nil, errors.New("SetObjectAclInput is nil") 146 } 147 output = &BaseModel{} 148 err = obsClient.doActionWithBucketAndKey("SetObjectAcl", HTTP_PUT, input.Bucket, input.Key, input, output, extensions) 149 if err != nil { 150 output = nil 151 } 152 return 153 } 154 155 // GetObjectAcl gets the ACL of an object. 156 // 157 // You can use this API to obtain the ACL of an object in a specified bucket. 158 func (obsClient ObsClient) GetObjectAcl(input *GetObjectAclInput, extensions ...extensionOptions) (output *GetObjectAclOutput, err error) { 159 if input == nil { 160 return nil, errors.New("GetObjectAclInput is nil") 161 } 162 output = &GetObjectAclOutput{} 163 err = obsClient.doActionWithBucketAndKey("GetObjectAcl", HTTP_GET, input.Bucket, input.Key, input, output, extensions) 164 if err != nil { 165 output = nil 166 } else { 167 if versionID, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok { 168 output.VersionId = versionID[0] 169 } 170 } 171 return 172 } 173 174 // RestoreObject restores an object. 175 func (obsClient ObsClient) RestoreObject(input *RestoreObjectInput, extensions ...extensionOptions) (output *BaseModel, err error) { 176 if input == nil { 177 return nil, errors.New("RestoreObjectInput is nil") 178 } 179 output = &BaseModel{} 180 err = obsClient.doActionWithBucketAndKey("RestoreObject", HTTP_POST, input.Bucket, input.Key, input, output, extensions) 181 if err != nil { 182 output = nil 183 } 184 return 185 } 186 187 // GetObjectMetadata gets object metadata. 188 // 189 // You can use this API to send a HEAD request to the object of a specified bucket to obtain its metadata. 190 func (obsClient ObsClient) GetObjectMetadata(input *GetObjectMetadataInput, extensions ...extensionOptions) (output *GetObjectMetadataOutput, err error) { 191 if input == nil { 192 return nil, errors.New("GetObjectMetadataInput is nil") 193 } 194 output = &GetObjectMetadataOutput{} 195 err = obsClient.doActionWithBucketAndKey("GetObjectMetadata", HTTP_HEAD, input.Bucket, input.Key, input, output, extensions) 196 if err != nil { 197 output = nil 198 } else { 199 ParseGetObjectMetadataOutput(output) 200 } 201 return 202 } 203 204 func (obsClient ObsClient) GetAttribute(input *GetAttributeInput, extensions ...extensionOptions) (output *GetAttributeOutput, err error) { 205 if input == nil { 206 return nil, errors.New("GetAttributeInput is nil") 207 } 208 output = &GetAttributeOutput{} 209 err = obsClient.doActionWithBucketAndKey("GetAttribute", HTTP_HEAD, input.Bucket, input.Key, input, output, extensions) 210 if err != nil { 211 output = nil 212 } else { 213 ParseGetAttributeOutput(output) 214 } 215 return 216 } 217 218 // GetObject downloads object. 219 // 220 // You can use this API to download an object in a specified bucket. 221 func (obsClient ObsClient) GetObject(input *GetObjectInput, extensions ...extensionOptions) (output *GetObjectOutput, err error) { 222 if input == nil { 223 return nil, errors.New("GetObjectInput is nil") 224 } 225 output = &GetObjectOutput{} 226 err = obsClient.doActionWithBucketAndKeyWithProgress(GET_OBJECT, HTTP_GET, input.Bucket, input.Key, input, output, extensions, nil) 227 if err != nil { 228 output = nil 229 return 230 } 231 232 ParseGetObjectOutput(output) 233 listener := obsClient.getProgressListener(extensions) 234 if listener != nil { 235 output.Body = TeeReader(output.Body, output.ContentLength, listener, nil) 236 } 237 return 238 } 239 240 func (obsClient ObsClient) GetObjectWithoutProgress(input *GetObjectInput, extensions ...extensionOptions) (output *GetObjectOutput, err error) { 241 if input == nil { 242 return nil, errors.New("GetObjectInput is nil") 243 } 244 output = &GetObjectOutput{} 245 err = obsClient.doActionWithBucketAndKeyWithProgress(GET_OBJECT, HTTP_GET, input.Bucket, input.Key, input, output, extensions, nil) 246 if err != nil { 247 output = nil 248 return 249 } 250 251 ParseGetObjectOutput(output) 252 return 253 } 254 255 // PutObject uploads an object to the specified bucket. 256 func (obsClient ObsClient) PutObject(input *PutObjectInput, extensions ...extensionOptions) (output *PutObjectOutput, err error) { 257 if input == nil { 258 return nil, errors.New("PutObjectInput is nil") 259 } 260 261 if input.ContentType == "" && input.Key != "" { 262 if contentType, ok := GetContentType(input.Key); ok { 263 input.ContentType = contentType 264 } 265 } 266 output = &PutObjectOutput{} 267 var repeatable bool 268 if input.Body != nil { 269 if _, ok := input.Body.(*strings.Reader); ok { 270 repeatable = true 271 } 272 if input.ContentLength > 0 { 273 input.Body = &readerWrapper{reader: input.Body, totalCount: input.ContentLength} 274 } 275 } 276 277 listener := obsClient.getProgressListener(extensions) 278 if repeatable { 279 err = obsClient.doActionWithBucketAndKeyWithProgress(PUT_OBJECT, HTTP_PUT, input.Bucket, input.Key, input, output, extensions, listener) 280 } else { 281 err = obsClient.doActionWithBucketAndKeyUnRepeatableWithProgress(PUT_OBJECT, HTTP_PUT, input.Bucket, input.Key, input, output, extensions, listener) 282 } 283 if err != nil { 284 output = nil 285 return 286 } 287 ParsePutObjectOutput(output) 288 output.ObjectUrl = fmt.Sprintf("%s/%s/%s", obsClient.conf.endpoint, input.Bucket, input.Key) 289 return 290 } 291 292 func (obsClient ObsClient) getContentType(input *PutObjectInput, sourceFile string) (contentType string) { 293 if contentType, ok := GetContentType(input.Key); ok { 294 return contentType 295 } 296 if contentType, ok := GetContentType(sourceFile); ok { 297 return contentType 298 } 299 return 300 } 301 302 func (obsClient ObsClient) isGetContentType(input *PutObjectInput) bool { 303 if input.ContentType == "" && input.Key != "" { 304 return true 305 } 306 return false 307 } 308 309 func (obsClient ObsClient) NewFolder(input *NewFolderInput, extensions ...extensionOptions) (output *NewFolderOutput, err error) { 310 if input == nil { 311 return nil, errors.New("NewFolderInput is nil") 312 } 313 314 if !strings.HasSuffix(input.Key, "/") { 315 input.Key += "/" 316 } 317 318 output = &NewFolderOutput{} 319 err = obsClient.doActionWithBucketAndKey("NewFolder", HTTP_PUT, input.Bucket, input.Key, input, output, extensions) 320 if err != nil { 321 output = nil 322 } else { 323 ParseNewFolderOutput(output) 324 output.ObjectUrl = fmt.Sprintf("%s/%s/%s", obsClient.conf.endpoint, input.Bucket, input.Key) 325 } 326 return 327 } 328 329 // PutFile uploads a file to the specified bucket. 330 func (obsClient ObsClient) PutFile(input *PutFileInput, extensions ...extensionOptions) (output *PutObjectOutput, err error) { 331 if input == nil { 332 return nil, errors.New("PutFileInput is nil") 333 } 334 335 var body io.Reader 336 sourceFile := strings.TrimSpace(input.SourceFile) 337 if sourceFile != "" { 338 fd, _err := os.Open(sourceFile) 339 if _err != nil { 340 err = _err 341 return nil, err 342 } 343 defer func() { 344 errMsg := fd.Close() 345 if errMsg != nil { 346 doLog(LEVEL_WARN, "Failed to close file with reason: %v", errMsg) 347 } 348 }() 349 350 stat, _err := fd.Stat() 351 if _err != nil { 352 err = _err 353 return nil, err 354 } 355 fileReaderWrapper := &fileReaderWrapper{filePath: sourceFile} 356 fileReaderWrapper.reader = fd 357 if input.ContentLength > 0 { 358 if input.ContentLength > stat.Size() { 359 input.ContentLength = stat.Size() 360 } 361 fileReaderWrapper.totalCount = input.ContentLength 362 } else { 363 fileReaderWrapper.totalCount = stat.Size() 364 } 365 body = fileReaderWrapper 366 } 367 368 _input := &PutObjectInput{} 369 _input.PutObjectBasicInput = input.PutObjectBasicInput 370 _input.Body = body 371 372 if obsClient.isGetContentType(_input) { 373 _input.ContentType = obsClient.getContentType(_input, sourceFile) 374 } 375 listener := obsClient.getProgressListener(extensions) 376 output = &PutObjectOutput{} 377 err = obsClient.doActionWithBucketAndKeyWithProgress(PUT_FILE, HTTP_PUT, _input.Bucket, _input.Key, _input, output, extensions, listener) 378 379 if err != nil { 380 output = nil 381 return 382 } 383 384 ParsePutObjectOutput(output) 385 output.ObjectUrl = fmt.Sprintf("%s/%s/%s", obsClient.conf.endpoint, input.Bucket, input.Key) 386 return 387 } 388 389 // CopyObject creates a copy for an existing object. 390 // 391 // You can use this API to create a copy for an object in a specified bucket. 392 func (obsClient ObsClient) CopyObject(input *CopyObjectInput, extensions ...extensionOptions) (output *CopyObjectOutput, err error) { 393 if input == nil { 394 return nil, errors.New("CopyObjectInput is nil") 395 } 396 397 if strings.TrimSpace(input.CopySourceBucket) == "" { 398 return nil, errors.New("Source bucket is empty") 399 } 400 if strings.TrimSpace(input.CopySourceKey) == "" { 401 return nil, errors.New("Source key is empty") 402 } 403 404 output = &CopyObjectOutput{} 405 err = obsClient.doActionWithBucketAndKey("CopyObject", HTTP_PUT, input.Bucket, input.Key, input, output, extensions) 406 if err != nil { 407 output = nil 408 } else { 409 ParseCopyObjectOutput(output) 410 } 411 return 412 } 413 414 func (obsClient ObsClient) AppendObject(input *AppendObjectInput, extensions ...extensionOptions) (output *AppendObjectOutput, err error) { 415 if input == nil { 416 return nil, errors.New("AppendObjectInput is nil") 417 } 418 419 if input.ContentType == "" && input.Key != "" { 420 if contentType, ok := mimeTypes[strings.ToLower(input.Key[strings.LastIndex(input.Key, ".")+1:])]; ok { 421 input.ContentType = contentType 422 } 423 } 424 output = &AppendObjectOutput{} 425 var repeatable bool 426 if input.Body != nil { 427 if _, ok := input.Body.(*strings.Reader); ok { 428 repeatable = true 429 } 430 if input.ContentLength > 0 { 431 input.Body = &readerWrapper{reader: input.Body, totalCount: input.ContentLength} 432 } 433 } 434 listener := obsClient.getProgressListener(extensions) 435 436 if repeatable { 437 err = obsClient.doActionWithBucketAndKeyWithProgress(APPEND_OBJECT, HTTP_POST, input.Bucket, input.Key, input, output, extensions, listener) 438 } else { 439 err = obsClient.doActionWithBucketAndKeyUnRepeatableWithProgress(APPEND_OBJECT, HTTP_POST, input.Bucket, input.Key, input, output, extensions, listener) 440 } 441 442 if err != nil || ParseAppendObjectOutput(output) != nil { 443 output = nil 444 } 445 return 446 } 447 448 func (obsClient ObsClient) ModifyObject(input *ModifyObjectInput, extensions ...extensionOptions) (output *ModifyObjectOutput, err error) { 449 if input == nil { 450 return nil, errors.New("ModifyObjectInput is nil") 451 } 452 453 output = &ModifyObjectOutput{} 454 var repeatable bool 455 if input.Body != nil { 456 if _, ok := input.Body.(*strings.Reader); ok { 457 repeatable = true 458 } 459 if input.ContentLength > 0 { 460 input.Body = &readerWrapper{reader: input.Body, totalCount: input.ContentLength} 461 } 462 } 463 if repeatable { 464 err = obsClient.doActionWithBucketAndKey("ModifyObject", HTTP_PUT, input.Bucket, input.Key, input, output, extensions) 465 } else { 466 err = obsClient.doActionWithBucketAndKeyUnRepeatable("ModifyObject", HTTP_PUT, input.Bucket, input.Key, input, output, extensions) 467 } 468 if err != nil { 469 output = nil 470 } else { 471 ParseModifyObjectOutput(output) 472 } 473 return 474 } 475 476 func (obsClient ObsClient) RenameFile(input *RenameFileInput, extensions ...extensionOptions) (output *RenameFileOutput, err error) { 477 if input == nil { 478 return nil, errors.New("RenameFileInput is nil") 479 } 480 481 output = &RenameFileOutput{} 482 err = obsClient.doActionWithBucketAndKey("RenameFile", HTTP_POST, input.Bucket, input.Key, input, output, extensions) 483 if err != nil { 484 output = nil 485 } 486 return 487 } 488 489 func (obsClient ObsClient) RenameFolder(input *RenameFolderInput, extensions ...extensionOptions) (output *RenameFolderOutput, err error) { 490 if input == nil { 491 return nil, errors.New("RenameFolderInput is nil") 492 } 493 494 if !strings.HasSuffix(input.Key, "/") { 495 input.Key += "/" 496 } 497 if !strings.HasSuffix(input.NewObjectKey, "/") { 498 input.NewObjectKey += "/" 499 } 500 output = &RenameFolderOutput{} 501 err = obsClient.doActionWithBucketAndKey("RenameFolder", HTTP_POST, input.Bucket, input.Key, input, output, extensions) 502 if err != nil { 503 output = nil 504 } 505 return 506 }