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  }