You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-library/vendor/github.com/baidubce/bce-sdk-go/services/bos/client.go

2255 lines
76 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright 2017 Baidu, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions
* and limitations under the License.
*/
// client.go - define the client for BOS service
// Package bos defines the BOS services of BCE. The supported APIs are all defined in sub-package
// model with three types: 16 bucket APIs, 9 object APIs and 7 multipart APIs.
package bos
import (
"encoding/json"
"errors"
"fmt"
"io"
"math"
"net/http"
"os"
"github.com/baidubce/bce-sdk-go/auth"
"github.com/baidubce/bce-sdk-go/bce"
sdk_http "github.com/baidubce/bce-sdk-go/http"
"github.com/baidubce/bce-sdk-go/services/bos/api"
"github.com/baidubce/bce-sdk-go/services/sts"
"github.com/baidubce/bce-sdk-go/util/log"
)
const (
DEFAULT_SERVICE_DOMAIN = bce.DEFAULT_REGION + ".bcebos.com"
DEFAULT_MAX_PARALLEL = 10
MULTIPART_ALIGN = 1 << 20 // 1MB
MIN_MULTIPART_SIZE = 100 * (1 << 10) // 100 KB
DEFAULT_MULTIPART_SIZE = 12 * (1 << 20) // 12MB
MAX_PART_NUMBER = 10000
MAX_SINGLE_PART_SIZE = 5 * (1 << 30) // 5GB
MAX_SINGLE_OBJECT_SIZE = 48.8 * (1 << 40) // 48.8TB
)
// Client of BOS service is a kind of BceClient, so derived from BceClient
type Client struct {
*bce.BceClient
// Fileds that used in parallel operation for BOS service
MaxParallel int64
MultipartSize int64
}
// BosClientConfiguration defines the config components structure by user.
type BosClientConfiguration struct {
Ak string
Sk string
Endpoint string
RedirectDisabled bool
}
// NewClient make the BOS service client with default configuration.
// Use `cli.Config.xxx` to access the config or change it to non-default value.
func NewClient(ak, sk, endpoint string) (*Client, error) {
return NewClientWithConfig(&BosClientConfiguration{
Ak: ak,
Sk: sk,
Endpoint: endpoint,
RedirectDisabled: false,
})
}
// NewStsClient make the BOS service client with STS configuration, it will first apply stsAK,stsSK, sessionToken, then return bosClient using temporary sts Credential
func NewStsClient(ak, sk, endpoint string, expiration int) (*Client, error) {
stsClient, err := sts.NewClient(ak, sk)
if err != nil {
fmt.Println("create sts client object :", err)
return nil, err
}
sts, err := stsClient.GetSessionToken(expiration, "")
if err != nil {
fmt.Println("get session token failed:", err)
return nil, err
}
bosClient, err := NewClient(sts.AccessKeyId, sts.SecretAccessKey, endpoint)
if err != nil {
fmt.Println("create bos client failed:", err)
return nil, err
}
stsCredential, err := auth.NewSessionBceCredentials(
sts.AccessKeyId,
sts.SecretAccessKey,
sts.SessionToken)
if err != nil {
fmt.Println("create sts credential object failed:", err)
return nil, err
}
bosClient.Config.Credentials = stsCredential
return bosClient, nil
}
func NewClientWithConfig(config *BosClientConfiguration) (*Client, error) {
var credentials *auth.BceCredentials
var err error
ak, sk, endpoint := config.Ak, config.Sk, config.Endpoint
if len(ak) == 0 && len(sk) == 0 { // to support public-read-write request
credentials, err = nil, nil
} else {
credentials, err = auth.NewBceCredentials(ak, sk)
if err != nil {
return nil, err
}
}
if len(endpoint) == 0 {
endpoint = DEFAULT_SERVICE_DOMAIN
}
defaultSignOptions := &auth.SignOptions{
HeadersToSign: auth.DEFAULT_HEADERS_TO_SIGN,
ExpireSeconds: auth.DEFAULT_EXPIRE_SECONDS}
defaultConf := &bce.BceClientConfiguration{
Endpoint: endpoint,
Region: bce.DEFAULT_REGION,
UserAgent: bce.DEFAULT_USER_AGENT,
Credentials: credentials,
SignOption: defaultSignOptions,
Retry: bce.DEFAULT_RETRY_POLICY,
ConnectionTimeoutInMillis: bce.DEFAULT_CONNECTION_TIMEOUT_IN_MILLIS,
RedirectDisabled: config.RedirectDisabled}
v1Signer := &auth.BceV1Signer{}
client := &Client{bce.NewBceClient(defaultConf, v1Signer),
DEFAULT_MAX_PARALLEL, DEFAULT_MULTIPART_SIZE}
return client, nil
}
// ListBuckets - list all buckets
//
// RETURNS:
// - *api.ListBucketsResult: the all buckets
// - error: the return error if any occurs
func (c *Client) ListBuckets() (*api.ListBucketsResult, error) {
return api.ListBuckets(c)
}
// ListObjects - list all objects of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - args: the optional arguments to list objects
// RETURNS:
// - *api.ListObjectsResult: the all objects of the bucket
// - error: the return error if any occurs
func (c *Client) ListObjects(bucket string,
args *api.ListObjectsArgs) (*api.ListObjectsResult, error) {
return api.ListObjects(c, bucket, args)
}
// SimpleListObjects - list all objects of the given bucket with simple arguments
//
// PARAMS:
// - bucket: the bucket name
// - prefix: the prefix for listing
// - maxKeys: the max number of result objects
// - marker: the marker to mark the beginning for the listing
// - delimiter: the delimiter for list objects
// RETURNS:
// - *api.ListObjectsResult: the all objects of the bucket
// - error: the return error if any occurs
func (c *Client) SimpleListObjects(bucket, prefix string, maxKeys int, marker,
delimiter string) (*api.ListObjectsResult, error) {
args := &api.ListObjectsArgs{delimiter, marker, maxKeys, prefix}
return api.ListObjects(c, bucket, args)
}
// HeadBucket - test the given bucket existed and access authority
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if exists and have authority otherwise the specific error
func (c *Client) HeadBucket(bucket string) error {
err, _ := api.HeadBucket(c, bucket)
return err
}
// DoesBucketExist - test the given bucket existed or not
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - bool: true if exists and false if not exists or occurs error
// - error: nil if exists or not exist, otherwise the specific error
func (c *Client) DoesBucketExist(bucket string) (bool, error) {
err, _ := api.HeadBucket(c, bucket)
if err == nil {
return true, nil
}
if realErr, ok := err.(*bce.BceServiceError); ok {
if realErr.StatusCode == http.StatusForbidden {
return true, nil
}
if realErr.StatusCode == http.StatusNotFound {
return false, nil
}
}
return false, err
}
//IsNsBucket - test the given bucket is namespace bucket or not
func (c *Client) IsNsBucket(bucket string) bool {
err, resp := api.HeadBucket(c, bucket)
if err == nil && resp.Header(sdk_http.BCE_BUCKET_TYPE) == api.NAMESPACE_BUCKET {
return true
}
if realErr, ok := err.(*bce.BceServiceError); ok {
if realErr.StatusCode == http.StatusForbidden &&
resp.Header(sdk_http.BCE_BUCKET_TYPE) == api.NAMESPACE_BUCKET {
return true
}
}
return false
}
// PutBucket - create a new bucket
//
// PARAMS:
// - bucket: the new bucket name
// RETURNS:
// - string: the location of the new bucket if create success
// - error: nil if create success otherwise the specific error
func (c *Client) PutBucket(bucket string) (string, error) {
return api.PutBucket(c, bucket)
}
// DeleteBucket - delete a empty bucket
//
// PARAMS:
// - bucket: the bucket name to be deleted
// RETURNS:
// - error: nil if delete success otherwise the specific error
func (c *Client) DeleteBucket(bucket string) error {
return api.DeleteBucket(c, bucket)
}
// GetBucketLocation - get the location fo the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - string: the location of the bucket
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketLocation(bucket string) (string, error) {
return api.GetBucketLocation(c, bucket)
}
// PutBucketAcl - set the acl of the given bucket with acl body stream
//
// PARAMS:
// - bucket: the bucket name
// - aclBody: the acl json body stream
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketAcl(bucket string, aclBody *bce.Body) error {
return api.PutBucketAcl(c, bucket, "", aclBody)
}
// PutBucketAclFromCanned - set the canned acl of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - cannedAcl: the cannedAcl string
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketAclFromCanned(bucket, cannedAcl string) error {
return api.PutBucketAcl(c, bucket, cannedAcl, nil)
}
// PutBucketAclFromFile - set the acl of the given bucket with acl json file name
//
// PARAMS:
// - bucket: the bucket name
// - aclFile: the acl file name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketAclFromFile(bucket, aclFile string) error {
body, err := bce.NewBodyFromFile(aclFile)
if err != nil {
return err
}
return api.PutBucketAcl(c, bucket, "", body)
}
// PutBucketAclFromString - set the acl of the given bucket with acl json string
//
// PARAMS:
// - bucket: the bucket name
// - aclString: the acl string with json format
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketAclFromString(bucket, aclString string) error {
body, err := bce.NewBodyFromString(aclString)
if err != nil {
return err
}
return api.PutBucketAcl(c, bucket, "", body)
}
// PutBucketAclFromStruct - set the acl of the given bucket with acl data structure
//
// PARAMS:
// - bucket: the bucket name
// - aclObj: the acl struct object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketAclFromStruct(bucket string, aclObj *api.PutBucketAclArgs) error {
jsonBytes, jsonErr := json.Marshal(aclObj)
if jsonErr != nil {
return jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return err
}
return api.PutBucketAcl(c, bucket, "", body)
}
// GetBucketAcl - get the acl of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - *api.GetBucketAclResult: the result of the bucket acl
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketAcl(bucket string) (*api.GetBucketAclResult, error) {
return api.GetBucketAcl(c, bucket)
}
// PutBucketLogging - set the loging setting of the given bucket with json stream
//
// PARAMS:
// - bucket: the bucket name
// - body: the json body
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketLogging(bucket string, body *bce.Body) error {
return api.PutBucketLogging(c, bucket, body)
}
// PutBucketLoggingFromString - set the loging setting of the given bucket with json string
//
// PARAMS:
// - bucket: the bucket name
// - logging: the json format string
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketLoggingFromString(bucket, logging string) error {
body, err := bce.NewBodyFromString(logging)
if err != nil {
return err
}
return api.PutBucketLogging(c, bucket, body)
}
// PutBucketLoggingFromStruct - set the loging setting of the given bucket with args object
//
// PARAMS:
// - bucket: the bucket name
// - obj: the logging setting object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketLoggingFromStruct(bucket string, obj *api.PutBucketLoggingArgs) error {
jsonBytes, jsonErr := json.Marshal(obj)
if jsonErr != nil {
return jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return err
}
return api.PutBucketLogging(c, bucket, body)
}
// GetBucketLogging - get the logging setting of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - *api.GetBucketLoggingResult: the logging setting of the bucket
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketLogging(bucket string) (*api.GetBucketLoggingResult, error) {
return api.GetBucketLogging(c, bucket)
}
// DeleteBucketLogging - delete the logging setting of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketLogging(bucket string) error {
return api.DeleteBucketLogging(c, bucket)
}
// PutBucketLifecycle - set the lifecycle rule of the given bucket with raw stream
//
// PARAMS:
// - bucket: the bucket name
// - lifecycle: the lifecycle rule json body
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketLifecycle(bucket string, lifecycle *bce.Body) error {
return api.PutBucketLifecycle(c, bucket, lifecycle)
}
// PutBucketLifecycleFromString - set the lifecycle rule of the given bucket with string
//
// PARAMS:
// - bucket: the bucket name
// - lifecycle: the lifecycle rule json format string body
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketLifecycleFromString(bucket, lifecycle string) error {
body, err := bce.NewBodyFromString(lifecycle)
if err != nil {
return err
}
return api.PutBucketLifecycle(c, bucket, body)
}
// GetBucketLifecycle - get the lifecycle rule of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - *api.GetBucketLifecycleResult: the lifecycle rule of the bucket
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketLifecycle(bucket string) (*api.GetBucketLifecycleResult, error) {
return api.GetBucketLifecycle(c, bucket)
}
// DeleteBucketLifecycle - delete the lifecycle rule of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketLifecycle(bucket string) error {
return api.DeleteBucketLifecycle(c, bucket)
}
// PutBucketStorageclass - set the storage class of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - storageClass: the storage class string value
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketStorageclass(bucket, storageClass string) error {
return api.PutBucketStorageclass(c, bucket, storageClass)
}
// GetBucketStorageclass - get the storage class of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - string: the storage class string value
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketStorageclass(bucket string) (string, error) {
return api.GetBucketStorageclass(c, bucket)
}
// PutBucketReplication - set the bucket replication config of different region
//
// PARAMS:
// - bucket: the bucket name
// - replicationConf: the replication config json body stream
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketReplication(bucket string, replicationConf *bce.Body, replicationRuleId string) error {
return api.PutBucketReplication(c, bucket, replicationConf, replicationRuleId)
}
// PutBucketReplicationFromFile - set the bucket replication config with json file name
//
// PARAMS:
// - bucket: the bucket name
// - confFile: the config json file name
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketReplicationFromFile(bucket, confFile string, replicationRuleId string) error {
body, err := bce.NewBodyFromFile(confFile)
if err != nil {
return err
}
return api.PutBucketReplication(c, bucket, body, replicationRuleId)
}
// PutBucketReplicationFromString - set the bucket replication config with json string
//
// PARAMS:
// - bucket: the bucket name
// - confString: the config string with json format
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketReplicationFromString(bucket, confString string, replicationRuleId string) error {
body, err := bce.NewBodyFromString(confString)
if err != nil {
return err
}
return api.PutBucketReplication(c, bucket, body, replicationRuleId)
}
// PutBucketReplicationFromStruct - set the bucket replication config with struct
//
// PARAMS:
// - bucket: the bucket name
// - confObj: the replication config struct object
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketReplicationFromStruct(bucket string,
confObj *api.PutBucketReplicationArgs, replicationRuleId string) error {
jsonBytes, jsonErr := json.Marshal(confObj)
if jsonErr != nil {
return jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return err
}
return api.PutBucketReplication(c, bucket, body, replicationRuleId)
}
// GetBucketReplication - get the bucket replication config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - *api.GetBucketReplicationResult: the result of the bucket replication config
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketReplication(bucket string, replicationRuleId string) (*api.GetBucketReplicationResult, error) {
return api.GetBucketReplication(c, bucket, replicationRuleId)
}
// ListBucketReplication - get all replication config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - *api.ListBucketReplicationResult: the list of the bucket replication config
// - error: nil if success otherwise the specific error
func (c *Client) ListBucketReplication(bucket string) (*api.ListBucketReplicationResult, error) {
return api.ListBucketReplication(c, bucket)
}
// DeleteBucketReplication - delete the bucket replication config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketReplication(bucket string, replicationRuleId string) error {
return api.DeleteBucketReplication(c, bucket, replicationRuleId)
}
// GetBucketReplicationProgress - get the bucket replication process of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - replicationRuleId: the replication rule id composed of [0-9 A-Z a-z _ -]
// RETURNS:
// - *api.GetBucketReplicationProgressResult: the process of the bucket replication
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketReplicationProgress(bucket string, replicationRuleId string) (
*api.GetBucketReplicationProgressResult, error) {
return api.GetBucketReplicationProgress(c, bucket, replicationRuleId)
}
// PutBucketEncryption - set the bucket encryption config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// - algorithm: the encryption algorithm name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketEncryption(bucket, algorithm string) error {
return api.PutBucketEncryption(c, bucket, algorithm)
}
// GetBucketEncryption - get the bucket encryption config
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - string: the encryption algorithm name
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketEncryption(bucket string) (string, error) {
return api.GetBucketEncryption(c, bucket)
}
// DeleteBucketEncryption - delete the bucket encryption config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketEncryption(bucket string) error {
return api.DeleteBucketEncryption(c, bucket)
}
// PutBucketStaticWebsite - set the bucket static website config
//
// PARAMS:
// - bucket: the bucket name
// - config: the static website config body stream
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketStaticWebsite(bucket string, config *bce.Body) error {
return api.PutBucketStaticWebsite(c, bucket, config)
}
// PutBucketStaticWebsiteFromString - set the bucket static website config from json string
//
// PARAMS:
// - bucket: the bucket name
// - jsonConfig: the static website config json string
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketStaticWebsiteFromString(bucket, jsonConfig string) error {
body, err := bce.NewBodyFromString(jsonConfig)
if err != nil {
return err
}
return api.PutBucketStaticWebsite(c, bucket, body)
}
// PutBucketStaticWebsiteFromStruct - set the bucket static website config from struct
//
// PARAMS:
// - bucket: the bucket name
// - confObj: the static website config object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketStaticWebsiteFromStruct(bucket string,
confObj *api.PutBucketStaticWebsiteArgs) error {
jsonBytes, jsonErr := json.Marshal(confObj)
if jsonErr != nil {
return jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return err
}
return api.PutBucketStaticWebsite(c, bucket, body)
}
// SimplePutBucketStaticWebsite - simple set the bucket static website config
//
// PARAMS:
// - bucket: the bucket name
// - index: the static website config for index file name
// - notFound: the static website config for notFound file name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) SimplePutBucketStaticWebsite(bucket, index, notFound string) error {
confObj := &api.PutBucketStaticWebsiteArgs{index, notFound}
return c.PutBucketStaticWebsiteFromStruct(bucket, confObj)
}
// GetBucketStaticWebsite - get the bucket static website config
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - result: the static website config result object
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketStaticWebsite(bucket string) (
*api.GetBucketStaticWebsiteResult, error) {
return api.GetBucketStaticWebsite(c, bucket)
}
// DeleteBucketStaticWebsite - delete the bucket static website config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketStaticWebsite(bucket string) error {
return api.DeleteBucketStaticWebsite(c, bucket)
}
// PutBucketCors - set the bucket CORS config
//
// PARAMS:
// - bucket: the bucket name
// - config: the bucket CORS config body stream
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketCors(bucket string, config *bce.Body) error {
return api.PutBucketCors(c, bucket, config)
}
// PutBucketCorsFromFile - set the bucket CORS config from json config file
//
// PARAMS:
// - bucket: the bucket name
// - filename: the bucket CORS json config file name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketCorsFromFile(bucket, filename string) error {
body, err := bce.NewBodyFromFile(filename)
if err != nil {
return err
}
return api.PutBucketCors(c, bucket, body)
}
// PutBucketCorsFromString - set the bucket CORS config from json config string
//
// PARAMS:
// - bucket: the bucket name
// - filename: the bucket CORS json config string
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketCorsFromString(bucket, jsonConfig string) error {
body, err := bce.NewBodyFromString(jsonConfig)
if err != nil {
return err
}
return api.PutBucketCors(c, bucket, body)
}
// PutBucketCorsFromStruct - set the bucket CORS config from json config object
//
// PARAMS:
// - bucket: the bucket name
// - filename: the bucket CORS json config object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketCorsFromStruct(bucket string, confObj *api.PutBucketCorsArgs) error {
jsonBytes, jsonErr := json.Marshal(confObj)
if jsonErr != nil {
return jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return err
}
return api.PutBucketCors(c, bucket, body)
}
// GetBucketCors - get the bucket CORS config
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - result: the bucket CORS config result object
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketCors(bucket string) (*api.GetBucketCorsResult, error) {
return api.GetBucketCors(c, bucket)
}
// DeleteBucketCors - delete the bucket CORS config of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketCors(bucket string) error {
return api.DeleteBucketCors(c, bucket)
}
// PutBucketCopyrightProtection - set the copyright protection config of the given bucket
//
// PARAMS:
// - cli: the client agent which can perform sending request
// - bucket: the bucket name
// - resources: the resource items in the bucket to be protected
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketCopyrightProtection(bucket string, resources ...string) error {
return api.PutBucketCopyrightProtection(c, bucket, resources...)
}
// GetBucketCopyrightProtection - get the bucket copyright protection config
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - result: the bucket copyright protection config resources
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketCopyrightProtection(bucket string) ([]string, error) {
return api.GetBucketCopyrightProtection(c, bucket)
}
// DeleteBucketCopyrightProtection - delete the bucket copyright protection config
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketCopyrightProtection(bucket string) error {
return api.DeleteBucketCopyrightProtection(c, bucket)
}
// PutObject - upload a new object or rewrite the existed object with raw stream
//
// PARAMS:
// - bucket: the name of the bucket to store the object
// - object: the name of the object
// - body: the object content body
// - args: the optional arguments
// RETURNS:
// - string: etag of the uploaded object
// - error: the uploaded error if any occurs
func (c *Client) PutObject(bucket, object string, body *bce.Body,
args *api.PutObjectArgs) (string, error) {
return api.PutObject(c, bucket, object, body, args)
}
// BasicPutObject - the basic interface of uploading an object
//
// PARAMS:
// - bucket: the name of the bucket to store the object
// - object: the name of the object
// - body: the object content body
// RETURNS:
// - string: etag of the uploaded object
// - error: the uploaded error if any occurs
func (c *Client) BasicPutObject(bucket, object string, body *bce.Body) (string, error) {
return api.PutObject(c, bucket, object, body, nil)
}
// PutObjectFromBytes - upload a new object or rewrite the existed object from a byte array
//
// PARAMS:
// - bucket: the name of the bucket to store the object
// - object: the name of the object
// - bytesArr: the content byte array
// - args: the optional arguments
// RETURNS:
// - string: etag of the uploaded object
// - error: the uploaded error if any occurs
func (c *Client) PutObjectFromBytes(bucket, object string, bytesArr []byte,
args *api.PutObjectArgs) (string, error) {
body, err := bce.NewBodyFromBytes(bytesArr)
if err != nil {
return "", err
}
return api.PutObject(c, bucket, object, body, args)
}
// PutObjectFromString - upload a new object or rewrite the existed object from a string
//
// PARAMS:
// - bucket: the name of the bucket to store the object
// - object: the name of the object
// - content: the content string
// - args: the optional arguments
// RETURNS:
// - string: etag of the uploaded object
// - error: the uploaded error if any occurs
func (c *Client) PutObjectFromString(bucket, object, content string,
args *api.PutObjectArgs) (string, error) {
body, err := bce.NewBodyFromString(content)
if err != nil {
return "", err
}
return api.PutObject(c, bucket, object, body, args)
}
// PutObjectFromFile - upload a new object or rewrite the existed object from a local file
//
// PARAMS:
// - bucket: the name of the bucket to store the object
// - object: the name of the object
// - fileName: the local file full path name
// - args: the optional arguments
// RETURNS:
// - string: etag of the uploaded object
// - error: the uploaded error if any occurs
func (c *Client) PutObjectFromFile(bucket, object, fileName string,
args *api.PutObjectArgs) (string, error) {
body, err := bce.NewBodyFromFile(fileName)
if err != nil {
return "", err
}
return api.PutObject(c, bucket, object, body, args)
}
// PutObjectFromStream - upload a new object or rewrite the existed object from stream
//
// PARAMS:
// - bucket: the name of the bucket to store the object
// - object: the name of the object
// - fileName: the local file full path name
// - args: the optional arguments
// RETURNS:
// - string: etag of the uploaded object
// - error: the uploaded error if any occurs
func (c *Client) PutObjectFromStream(bucket, object string, reader io.Reader,
args *api.PutObjectArgs) (string, error) {
body, err := bce.NewBodyFromSizedReader(reader, -1)
if err != nil {
return "", err
}
return api.PutObject(c, bucket, object, body, args)
}
// CopyObject - copy a remote object to another one
//
// PARAMS:
// - bucket: the name of the destination bucket
// - object: the name of the destination object
// - srcBucket: the name of the source bucket
// - srcObject: the name of the source object
// - args: the optional arguments for copying object which are MetadataDirective, StorageClass,
// IfMatch, IfNoneMatch, ifModifiedSince, IfUnmodifiedSince
// RETURNS:
// - *api.CopyObjectResult: result struct which contains "ETag" and "LastModified" fields
// - error: any error if it occurs
func (c *Client) CopyObject(bucket, object, srcBucket, srcObject string,
args *api.CopyObjectArgs) (*api.CopyObjectResult, error) {
source := fmt.Sprintf("/%s/%s", srcBucket, srcObject)
return api.CopyObject(c, bucket, object, source, args)
}
// BasicCopyObject - the basic interface of copying a object to another one
//
// PARAMS:
// - bucket: the name of the destination bucket
// - object: the name of the destination object
// - srcBucket: the name of the source bucket
// - srcObject: the name of the source object
// RETURNS:
// - *api.CopyObjectResult: result struct which contains "ETag" and "LastModified" fields
// - error: any error if it occurs
func (c *Client) BasicCopyObject(bucket, object, srcBucket,
srcObject string) (*api.CopyObjectResult, error) {
source := fmt.Sprintf("/%s/%s", srcBucket, srcObject)
return api.CopyObject(c, bucket, object, source, nil)
}
// GetObject - get the given object with raw stream return
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - args: the optional args in querysring
// - ranges: the optional range start and end to get the given object
// RETURNS:
// - *api.GetObjectResult: result struct which contains "Body" and header fields
// for details reference https://cloud.baidu.com/doc/BOS/API.html#GetObject.E6.8E.A5.E5.8F.A3
// - error: any error if it occurs
func (c *Client) GetObject(bucket, object string, args map[string]string,
ranges ...int64) (*api.GetObjectResult, error) {
return api.GetObject(c, bucket, object, args, ranges...)
}
// BasicGetObject - the basic interface of geting the given object
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// RETURNS:
// - *api.GetObjectResult: result struct which contains "Body" and header fields
// for details reference https://cloud.baidu.com/doc/BOS/API.html#GetObject.E6.8E.A5.E5.8F.A3
// - error: any error if it occurs
func (c *Client) BasicGetObject(bucket, object string) (*api.GetObjectResult, error) {
return api.GetObject(c, bucket, object, nil)
}
// BasicGetObjectToFile - use basic interface to get the given object to the given file path
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - filePath: the file path to store the object content
// RETURNS:
// - error: any error if it occurs
func (c *Client) BasicGetObjectToFile(bucket, object, filePath string) error {
res, err := api.GetObject(c, bucket, object, nil)
if err != nil {
return err
}
defer res.Body.Close()
file, fileErr := os.OpenFile(filePath, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
if fileErr != nil {
return fileErr
}
defer file.Close()
written, writeErr := io.CopyN(file, res.Body, res.ContentLength)
if writeErr != nil {
return writeErr
}
if written != res.ContentLength {
return fmt.Errorf("written content size does not match the response content")
}
return nil
}
// GetObjectMeta - get the given object metadata
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// RETURNS:
// - *api.GetObjectMetaResult: metadata result, for details reference
// https://cloud.baidu.com/doc/BOS/API.html#GetObjectMeta.E6.8E.A5.E5.8F.A3
// - error: any error if it occurs
func (c *Client) GetObjectMeta(bucket, object string) (*api.GetObjectMetaResult, error) {
return api.GetObjectMeta(c, bucket, object)
}
// SelectObject - select the object content
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - args: the optional arguments to select the object
// RETURNS:
// - *api.SelectObjectResult: select object result
// - error: any error if it occurs
func (c *Client) SelectObject(bucket, object string, args *api.SelectObjectArgs) (*api.SelectObjectResult, error) {
return api.SelectObject(c, bucket, object, args)
}
// FetchObject - fetch the object content from the given source and store
//
// PARAMS:
// - bucket: the name of the bucket to store
// - object: the name of the object to store
// - source: fetch source url
// - args: the optional arguments to fetch the object
// RETURNS:
// - *api.FetchObjectResult: result struct with Code, Message, RequestId and JobId fields
// - error: any error if it occurs
func (c *Client) FetchObject(bucket, object, source string,
args *api.FetchObjectArgs) (*api.FetchObjectResult, error) {
return api.FetchObject(c, bucket, object, source, args)
}
// BasicFetchObject - the basic interface of the fetch object api
//
// PARAMS:
// - bucket: the name of the bucket to store
// - object: the name of the object to store
// - source: fetch source url
// RETURNS:
// - *api.FetchObjectResult: result struct with Code, Message, RequestId and JobId fields
// - error: any error if it occurs
func (c *Client) BasicFetchObject(bucket, object, source string) (*api.FetchObjectResult, error) {
return api.FetchObject(c, bucket, object, source, nil)
}
// SimpleFetchObject - fetch object with simple arguments interface
//
// PARAMS:
// - bucket: the name of the bucket to store
// - object: the name of the object to store
// - source: fetch source url
// - mode: fetch mode which supports sync and async
// - storageClass: the storage class of the fetched object
// RETURNS:
// - *api.FetchObjectResult: result struct with Code, Message, RequestId and JobId fields
// - error: any error if it occurs
func (c *Client) SimpleFetchObject(bucket, object, source, mode,
storageClass string) (*api.FetchObjectResult, error) {
args := &api.FetchObjectArgs{mode, storageClass}
return api.FetchObject(c, bucket, object, source, args)
}
// AppendObject - append the given content to a new or existed object which is appendable
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - content: the append object stream
// - args: the optional arguments to append object
// RETURNS:
// - *api.AppendObjectResult: the result of the appended object
// - error: any error if it occurs
func (c *Client) AppendObject(bucket, object string, content *bce.Body,
args *api.AppendObjectArgs) (*api.AppendObjectResult, error) {
return api.AppendObject(c, bucket, object, content, args)
}
// SimpleAppendObject - the interface to append object with simple offset argument
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - content: the append object stream
// - offset: the offset of where to append
// RETURNS:
// - *api.AppendObjectResult: the result of the appended object
// - error: any error if it occurs
func (c *Client) SimpleAppendObject(bucket, object string, content *bce.Body,
offset int64) (*api.AppendObjectResult, error) {
return api.AppendObject(c, bucket, object, content, &api.AppendObjectArgs{Offset: offset})
}
// SimpleAppendObjectFromString - the simple interface of appending an object from a string
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - content: the object string to append
// - offset: the offset of where to append
// RETURNS:
// - *api.AppendObjectResult: the result of the appended object
// - error: any error if it occurs
func (c *Client) SimpleAppendObjectFromString(bucket, object, content string,
offset int64) (*api.AppendObjectResult, error) {
body, err := bce.NewBodyFromString(content)
if err != nil {
return nil, err
}
return api.AppendObject(c, bucket, object, body, &api.AppendObjectArgs{Offset: offset})
}
// SimpleAppendObjectFromFile - the simple interface of appending an object from a file
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - filePath: the full file path
// - offset: the offset of where to append
// RETURNS:
// - *api.AppendObjectResult: the result of the appended object
// - error: any error if it occurs
func (c *Client) SimpleAppendObjectFromFile(bucket, object, filePath string,
offset int64) (*api.AppendObjectResult, error) {
body, err := bce.NewBodyFromFile(filePath)
if err != nil {
return nil, err
}
return api.AppendObject(c, bucket, object, body, &api.AppendObjectArgs{Offset: offset})
}
// DeleteObject - delete the given object
//
// PARAMS:
// - bucket: the name of the bucket to delete
// - object: the name of the object to delete
// RETURNS:
// - error: any error if it occurs
func (c *Client) DeleteObject(bucket, object string) error {
return api.DeleteObject(c, bucket, object)
}
// DeleteMultipleObjects - delete a list of objects
//
// PARAMS:
// - bucket: the name of the bucket to delete
// - objectListStream: the object list stream to be deleted
// RETURNS:
// - *api.DeleteMultipleObjectsResult: the delete information
// - error: any error if it occurs
func (c *Client) DeleteMultipleObjects(bucket string,
objectListStream *bce.Body) (*api.DeleteMultipleObjectsResult, error) {
return api.DeleteMultipleObjects(c, bucket, objectListStream)
}
// DeleteMultipleObjectsFromString - delete a list of objects with json format string
//
// PARAMS:
// - bucket: the name of the bucket to delete
// - objectListString: the object list string to be deleted
// RETURNS:
// - *api.DeleteMultipleObjectsResult: the delete information
// - error: any error if it occurs
func (c *Client) DeleteMultipleObjectsFromString(bucket,
objectListString string) (*api.DeleteMultipleObjectsResult, error) {
body, err := bce.NewBodyFromString(objectListString)
if err != nil {
return nil, err
}
return api.DeleteMultipleObjects(c, bucket, body)
}
// DeleteMultipleObjectsFromStruct - delete a list of objects with object list struct
//
// PARAMS:
// - bucket: the name of the bucket to delete
// - objectListStruct: the object list struct to be deleted
// RETURNS:
// - *api.DeleteMultipleObjectsResult: the delete information
// - error: any error if it occurs
func (c *Client) DeleteMultipleObjectsFromStruct(bucket string,
objectListStruct *api.DeleteMultipleObjectsArgs) (*api.DeleteMultipleObjectsResult, error) {
jsonBytes, jsonErr := json.Marshal(objectListStruct)
if jsonErr != nil {
return nil, jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return nil, err
}
return api.DeleteMultipleObjects(c, bucket, body)
}
// DeleteMultipleObjectsFromKeyList - delete a list of objects with given key string array
//
// PARAMS:
// - bucket: the name of the bucket to delete
// - keyList: the key string list to be deleted
// RETURNS:
// - *api.DeleteMultipleObjectsResult: the delete information
// - error: any error if it occurs
func (c *Client) DeleteMultipleObjectsFromKeyList(bucket string,
keyList []string) (*api.DeleteMultipleObjectsResult, error) {
if len(keyList) == 0 {
return nil, fmt.Errorf("the key list to be deleted is empty")
}
args := make([]api.DeleteObjectArgs, len(keyList))
for i, k := range keyList {
args[i].Key = k
}
argsContainer := &api.DeleteMultipleObjectsArgs{args}
jsonBytes, jsonErr := json.Marshal(argsContainer)
if jsonErr != nil {
return nil, jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return nil, err
}
return api.DeleteMultipleObjects(c, bucket, body)
}
// InitiateMultipartUpload - initiate a multipart upload to get a upload ID
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - contentType: the content type of the object to be uploaded which should be specified,
// otherwise use the default(application/octet-stream)
// - args: the optional arguments
// RETURNS:
// - *InitiateMultipartUploadResult: the result data structure
// - error: nil if ok otherwise the specific error
func (c *Client) InitiateMultipartUpload(bucket, object, contentType string,
args *api.InitiateMultipartUploadArgs) (*api.InitiateMultipartUploadResult, error) {
return api.InitiateMultipartUpload(c, bucket, object, contentType, args)
}
// BasicInitiateMultipartUpload - basic interface to initiate a multipart upload
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// RETURNS:
// - *InitiateMultipartUploadResult: the result data structure
// - error: nil if ok otherwise the specific error
func (c *Client) BasicInitiateMultipartUpload(bucket,
object string) (*api.InitiateMultipartUploadResult, error) {
return api.InitiateMultipartUpload(c, bucket, object, "", nil)
}
// UploadPart - upload the single part in the multipart upload process
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - uploadId: the multipart upload id
// - partNumber: the current part number
// - content: the uploaded part content
// - args: the optional arguments
// RETURNS:
// - string: the etag of the uploaded part
// - error: nil if ok otherwise the specific error
func (c *Client) UploadPart(bucket, object, uploadId string, partNumber int,
content *bce.Body, args *api.UploadPartArgs) (string, error) {
return api.UploadPart(c, bucket, object, uploadId, partNumber, content, args)
}
// BasicUploadPart - basic interface to upload the single part in the multipart upload process
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - uploadId: the multipart upload id
// - partNumber: the current part number
// - content: the uploaded part content
// RETURNS:
// - string: the etag of the uploaded part
// - error: nil if ok otherwise the specific error
func (c *Client) BasicUploadPart(bucket, object, uploadId string, partNumber int,
content *bce.Body) (string, error) {
return api.UploadPart(c, bucket, object, uploadId, partNumber, content, nil)
}
// UploadPartFromBytes - upload the single part in the multipart upload process
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - uploadId: the multipart upload id
// - partNumber: the current part number
// - content: the uploaded part content
// - args: the optional arguments
// RETURNS:
// - string: the etag of the uploaded part
// - error: nil if ok otherwise the specific error
func (c *Client) UploadPartFromBytes(bucket, object, uploadId string, partNumber int,
content []byte, args *api.UploadPartArgs) (string, error) {
return api.UploadPartFromBytes(c, bucket, object, uploadId, partNumber, content, args)
}
// UploadPartCopy - copy the multipart object
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - srcBucket: the source bucket
// - srcObject: the source object
// - uploadId: the multipart upload id
// - partNumber: the current part number
// - args: the optional arguments
// RETURNS:
// - *CopyObjectResult: the lastModified and eTag of the part
// - error: nil if ok otherwise the specific error
func (c *Client) UploadPartCopy(bucket, object, srcBucket, srcObject, uploadId string,
partNumber int, args *api.UploadPartCopyArgs) (*api.CopyObjectResult, error) {
source := fmt.Sprintf("/%s/%s", srcBucket, srcObject)
return api.UploadPartCopy(c, bucket, object, source, uploadId, partNumber, args)
}
// BasicUploadPartCopy - basic interface to copy the multipart object
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - srcBucket: the source bucket
// - srcObject: the source object
// - uploadId: the multipart upload id
// - partNumber: the current part number
// RETURNS:
// - *CopyObjectResult: the lastModified and eTag of the part
// - error: nil if ok otherwise the specific error
func (c *Client) BasicUploadPartCopy(bucket, object, srcBucket, srcObject, uploadId string,
partNumber int) (*api.CopyObjectResult, error) {
source := fmt.Sprintf("/%s/%s", srcBucket, srcObject)
return api.UploadPartCopy(c, bucket, object, source, uploadId, partNumber, nil)
}
// CompleteMultipartUpload - finish a multipart upload operation with parts stream
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - uploadId: the multipart upload id
// - parts: all parts info stream
// - meta: user defined meta data
// RETURNS:
// - *CompleteMultipartUploadResult: the result data
// - error: nil if ok otherwise the specific error
func (c *Client) CompleteMultipartUpload(bucket, object, uploadId string,
body *bce.Body, args *api.CompleteMultipartUploadArgs) (*api.CompleteMultipartUploadResult, error) {
return api.CompleteMultipartUpload(c, bucket, object, uploadId, body, args)
}
// CompleteMultipartUploadFromStruct - finish a multipart upload operation with parts struct
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - uploadId: the multipart upload id
// - args: args info struct object
// RETURNS:
// - *CompleteMultipartUploadResult: the result data
// - error: nil if ok otherwise the specific error
func (c *Client) CompleteMultipartUploadFromStruct(bucket, object, uploadId string,
args *api.CompleteMultipartUploadArgs) (*api.CompleteMultipartUploadResult, error) {
jsonBytes, jsonErr := json.Marshal(args)
if jsonErr != nil {
return nil, jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return nil, err
}
return api.CompleteMultipartUpload(c, bucket, object, uploadId, body, args)
}
// AbortMultipartUpload - abort a multipart upload operation
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - uploadId: the multipart upload id
// RETURNS:
// - error: nil if ok otherwise the specific error
func (c *Client) AbortMultipartUpload(bucket, object, uploadId string) error {
return api.AbortMultipartUpload(c, bucket, object, uploadId)
}
// ListParts - list the successfully uploaded parts info by upload id
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - uploadId: the multipart upload id
// - args: the optional arguments
// RETURNS:
// - *ListPartsResult: the uploaded parts info result
// - error: nil if ok otherwise the specific error
func (c *Client) ListParts(bucket, object, uploadId string,
args *api.ListPartsArgs) (*api.ListPartsResult, error) {
return api.ListParts(c, bucket, object, uploadId, args)
}
// BasicListParts - basic interface to list the successfully uploaded parts info by upload id
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - uploadId: the multipart upload id
// RETURNS:
// - *ListPartsResult: the uploaded parts info result
// - error: nil if ok otherwise the specific error
func (c *Client) BasicListParts(bucket, object, uploadId string) (*api.ListPartsResult, error) {
return api.ListParts(c, bucket, object, uploadId, nil)
}
// ListMultipartUploads - list the unfinished uploaded parts of the given bucket
//
// PARAMS:
// - bucket: the destination bucket name
// - args: the optional arguments
// RETURNS:
// - *ListMultipartUploadsResult: the unfinished uploaded parts info result
// - error: nil if ok otherwise the specific error
func (c *Client) ListMultipartUploads(bucket string,
args *api.ListMultipartUploadsArgs) (*api.ListMultipartUploadsResult, error) {
return api.ListMultipartUploads(c, bucket, args)
}
// BasicListMultipartUploads - basic interface to list the unfinished uploaded parts
//
// PARAMS:
// - bucket: the destination bucket name
// RETURNS:
// - *ListMultipartUploadsResult: the unfinished uploaded parts info result
// - error: nil if ok otherwise the specific error
func (c *Client) BasicListMultipartUploads(bucket string) (
*api.ListMultipartUploadsResult, error) {
return api.ListMultipartUploads(c, bucket, nil)
}
// UploadSuperFile - parallel upload the super file by using the multipart upload interface
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - fileName: the local full path filename of the super file
// - storageClass: the storage class to be set to the uploaded file
// RETURNS:
// - error: nil if ok otherwise the specific error
func (c *Client) UploadSuperFile(bucket, object, fileName, storageClass string) error {
// Get the file size and check the size for multipart upload
file, fileErr := os.Open(fileName)
if fileErr != nil {
return fileErr
}
oldTimeout := c.Config.ConnectionTimeoutInMillis
c.Config.ConnectionTimeoutInMillis = 0
defer func() {
c.Config.ConnectionTimeoutInMillis = oldTimeout
file.Close()
}()
fileInfo, infoErr := file.Stat()
if infoErr != nil {
return infoErr
}
size := fileInfo.Size()
if size < MIN_MULTIPART_SIZE || c.MultipartSize < MIN_MULTIPART_SIZE {
return bce.NewBceClientError("multipart size should not be less than 1MB")
}
// Calculate part size and total part number
partSize := (c.MultipartSize + MULTIPART_ALIGN - 1) / MULTIPART_ALIGN * MULTIPART_ALIGN
partNum := (size + partSize - 1) / partSize
if partNum > MAX_PART_NUMBER {
partSize = (size + MAX_PART_NUMBER - 1) / MAX_PART_NUMBER
partSize = (partSize + MULTIPART_ALIGN - 1) / MULTIPART_ALIGN * MULTIPART_ALIGN
partNum = (size + partSize - 1) / partSize
}
log.Debugf("starting upload super file, total parts: %d, part size: %d", partNum, partSize)
// Inner wrapper function of parallel uploading each part to get the ETag of the part
uploadPart := func(bucket, object, uploadId string, partNumber int, body *bce.Body,
result chan *api.UploadInfoType, ret chan error, id int64, pool chan int64) {
etag, err := c.BasicUploadPart(bucket, object, uploadId, partNumber, body)
if err != nil {
result <- nil
ret <- err
} else {
result <- &api.UploadInfoType{partNumber, etag}
}
pool <- id
}
// Do the parallel multipart upload
resp, err := c.InitiateMultipartUpload(bucket, object, "",
&api.InitiateMultipartUploadArgs{StorageClass: storageClass})
if err != nil {
return err
}
uploadId := resp.UploadId
uploadedResult := make(chan *api.UploadInfoType, partNum)
retChan := make(chan error, partNum)
workerPool := make(chan int64, c.MaxParallel)
for i := int64(0); i < c.MaxParallel; i++ {
workerPool <- i
}
for partId := int64(1); partId <= partNum; partId++ {
uploadSize := partSize
offset := (partId - 1) * partSize
left := size - offset
if uploadSize > left {
uploadSize = left
}
partBody, _ := bce.NewBodyFromSectionFile(file, offset, uploadSize)
select { // wait until get a worker to upload
case workerId := <-workerPool:
go uploadPart(bucket, object, uploadId, int(partId), partBody,
uploadedResult, retChan, workerId, workerPool)
case uploadPartErr := <-retChan:
c.AbortMultipartUpload(bucket, object, uploadId)
return uploadPartErr
}
}
// Check the return of each part uploading, and decide to complete or abort it
completeArgs := &api.CompleteMultipartUploadArgs{
Parts: make([]api.UploadInfoType, partNum),
}
for i := partNum; i > 0; i-- {
uploaded := <-uploadedResult
if uploaded == nil { // error occurs and not be caught in `select' statement
c.AbortMultipartUpload(bucket, object, uploadId)
return <-retChan
}
completeArgs.Parts[uploaded.PartNumber-1] = *uploaded
log.Debugf("upload part %d success, etag: %s", uploaded.PartNumber, uploaded.ETag)
}
if _, err := c.CompleteMultipartUploadFromStruct(bucket, object,
uploadId, completeArgs); err != nil {
c.AbortMultipartUpload(bucket, object, uploadId)
return err
}
return nil
}
// DownloadSuperFile - parallel download the super file using the get object with range
//
// PARAMS:
// - bucket: the destination bucket name
// - object: the destination object name
// - fileName: the local full path filename to store the object
// RETURNS:
// - error: nil if ok otherwise the specific error
func (c *Client) DownloadSuperFile(bucket, object, fileName string) (err error) {
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
return
}
oldTimeout := c.Config.ConnectionTimeoutInMillis
c.Config.ConnectionTimeoutInMillis = 0
defer func() {
c.Config.ConnectionTimeoutInMillis = oldTimeout
file.Close()
if err != nil {
os.Remove(fileName)
}
}()
meta, err := c.GetObjectMeta(bucket, object)
if err != nil {
return
}
size := meta.ContentLength
partSize := (c.MultipartSize + MULTIPART_ALIGN - 1) / MULTIPART_ALIGN * MULTIPART_ALIGN
partNum := (size + partSize - 1) / partSize
log.Debugf("starting download super file, total parts: %d, part size: %d", partNum, partSize)
doneChan := make(chan struct{}, partNum)
abortChan := make(chan struct{})
// Set up multiple goroutine workers to download the object
workerPool := make(chan int64, c.MaxParallel)
for i := int64(0); i < c.MaxParallel; i++ {
workerPool <- i
}
for i := int64(0); i < partNum; i++ {
rangeStart := i * partSize
rangeEnd := (i+1)*partSize - 1
if rangeEnd > size-1 {
rangeEnd = size - 1
}
select {
case workerId := <-workerPool:
go func(rangeStart, rangeEnd, workerId int64) {
res, rangeGetErr := c.GetObject(bucket, object, nil, rangeStart, rangeEnd)
if rangeGetErr != nil {
log.Errorf("download object part(offset:%d, size:%d) failed: %v",
rangeStart, res.ContentLength, rangeGetErr)
abortChan <- struct{}{}
err = rangeGetErr
return
}
defer res.Body.Close()
log.Debugf("writing part %d with offset=%d, size=%d", rangeStart/partSize,
rangeStart, res.ContentLength)
buf := make([]byte, 4096)
offset := rangeStart
for {
n, e := res.Body.Read(buf)
if e != nil && e != io.EOF {
abortChan <- struct{}{}
err = e
return
}
if n == 0 {
break
}
if _, writeErr := file.WriteAt(buf[:n], offset); writeErr != nil {
abortChan <- struct{}{}
err = writeErr
return
}
offset += int64(n)
}
log.Debugf("writing part %d done", rangeStart/partSize)
workerPool <- workerId
doneChan <- struct{}{}
}(rangeStart, rangeEnd, workerId)
case <-abortChan: // abort range get if error occurs during downloading any part
return
}
}
// Wait for writing to local file done
for i := partNum; i > 0; i-- {
<-doneChan
}
return nil
}
// GeneratePresignedUrl - generate an authorization url with expire time and optional arguments
//
// PARAMS:
// - bucket: the target bucket name
// - object: the target object name
// - expireInSeconds: the expire time in seconds of the signed url
// - method: optional sign method, default is GET
// - headers: optional sign headers, default just set the Host
// - params: optional sign params, default is empty
// RETURNS:
// - string: the presigned url with authorization string
func (c *Client) GeneratePresignedUrl(bucket, object string, expireInSeconds int, method string,
headers, params map[string]string) string {
return api.GeneratePresignedUrl(c.Config, c.Signer, bucket, object,
expireInSeconds, method, headers, params)
}
func (c *Client) GeneratePresignedUrlPathStyle(bucket, object string, expireInSeconds int, method string,
headers, params map[string]string) string {
return api.GeneratePresignedUrlPathStyle(c.Config, c.Signer, bucket, object,
expireInSeconds, method, headers, params)
}
// BasicGeneratePresignedUrl - basic interface to generate an authorization url with expire time
//
// PARAMS:
// - bucket: the target bucket name
// - object: the target object name
// - expireInSeconds: the expire time in seconds of the signed url
// RETURNS:
// - string: the presigned url with authorization string
func (c *Client) BasicGeneratePresignedUrl(bucket, object string, expireInSeconds int) string {
return api.GeneratePresignedUrl(c.Config, c.Signer, bucket, object,
expireInSeconds, "", nil, nil)
}
// PutObjectAcl - set the ACL of the given object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - aclBody: the acl json body stream
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAcl(bucket, object string, aclBody *bce.Body) error {
return api.PutObjectAcl(c, bucket, object, "", nil, nil, aclBody)
}
// PutObjectAclFromCanned - set the canned acl of the given object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - cannedAcl: the cannedAcl string
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAclFromCanned(bucket, object, cannedAcl string) error {
return api.PutObjectAcl(c, bucket, object, cannedAcl, nil, nil, nil)
}
// PutObjectAclGrantRead - set the canned grant read acl of the given object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - ids: the user id list to grant read for this object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAclGrantRead(bucket, object string, ids ...string) error {
return api.PutObjectAcl(c, bucket, object, "", ids, nil, nil)
}
// PutObjectAclGrantFullControl - set the canned grant full-control acl of the given object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - ids: the user id list to grant full-control for this object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAclGrantFullControl(bucket, object string, ids ...string) error {
return api.PutObjectAcl(c, bucket, object, "", nil, ids, nil)
}
// PutObjectAclFromFile - set the acl of the given object with acl json file name
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - aclFile: the acl file name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAclFromFile(bucket, object, aclFile string) error {
body, err := bce.NewBodyFromFile(aclFile)
if err != nil {
return err
}
return api.PutObjectAcl(c, bucket, object, "", nil, nil, body)
}
// PutObjectAclFromString - set the acl of the given object with acl json string
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - aclString: the acl string with json format
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAclFromString(bucket, object, aclString string) error {
body, err := bce.NewBodyFromString(aclString)
if err != nil {
return err
}
return api.PutObjectAcl(c, bucket, object, "", nil, nil, body)
}
// PutObjectAclFromStruct - set the acl of the given object with acl data structure
//
// PARAMS:
// - bucket: the bucket name
// - aclObj: the acl struct object
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutObjectAclFromStruct(bucket, object string, aclObj *api.PutObjectAclArgs) error {
jsonBytes, jsonErr := json.Marshal(aclObj)
if jsonErr != nil {
return jsonErr
}
body, err := bce.NewBodyFromBytes(jsonBytes)
if err != nil {
return err
}
return api.PutObjectAcl(c, bucket, object, "", nil, nil, body)
}
// GetObjectAcl - get the acl of the given object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// RETURNS:
// - *api.GetObjectAclResult: the result of the object acl
// - error: nil if success otherwise the specific error
func (c *Client) GetObjectAcl(bucket, object string) (*api.GetObjectAclResult, error) {
return api.GetObjectAcl(c, bucket, object)
}
// DeleteObjectAcl - delete the acl of the given object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteObjectAcl(bucket, object string) error {
return api.DeleteObjectAcl(c, bucket, object)
}
// RestoreObject - restore the archive object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - restoreDays: the effective time of restore
// - restoreTier: the tier of restore
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) RestoreObject(bucket string, object string, restoreDays int, restoreTier string) error {
if _, ok := api.VALID_RESTORE_TIER[restoreTier]; !ok {
return errors.New("invalid restore tier")
}
if restoreDays <= 0 {
return errors.New("invalid restore days")
}
args := api.ArchiveRestoreArgs{
RestoreTier: restoreTier,
RestoreDays: restoreDays,
}
return api.RestoreObject(c, bucket, object, args)
}
// PutBucketTrash - put the bucket trash
//
// PARAMS:
// - bucket: the bucket name
// - trashReq: the trash request
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketTrash(bucket string, trashReq api.PutBucketTrashReq) error {
return api.PutBucketTrash(c, bucket, trashReq)
}
// GetBucketTrash - get the bucket trash
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - *api.GetBucketTrashResult,: the result of the bucket trash
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketTrash(bucket string) (*api.GetBucketTrashResult, error) {
return api.GetBucketTrash(c, bucket)
}
// DeleteBucketTrash - delete the trash of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketTrash(bucket string) error {
return api.DeleteBucketTrash(c, bucket)
}
// PutBucketNotification - put the bucket notification
//
// PARAMS:
// - bucket: the bucket name
// - putBucketNotificationReq: the bucket notification request
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) PutBucketNotification(bucket string, putBucketNotificationReq api.PutBucketNotificationReq) error {
return api.PutBucketNotification(c, bucket, putBucketNotificationReq)
}
// GetBucketNotification - get the bucket notification
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - *api.PutBucketNotificationReq,: the result of the bucket notification
// - error: nil if success otherwise the specific error
func (c *Client) GetBucketNotification(bucket string) (*api.PutBucketNotificationReq, error) {
return api.GetBucketNotification(c, bucket)
}
// DeleteBucketNotification - delete the notification of the given bucket
//
// PARAMS:
// - bucket: the bucket name
// RETURNS:
// - error: nil if success otherwise the specific error
func (c *Client) DeleteBucketNotification(bucket string) error {
return api.DeleteBucketNotification(c, bucket)
}
// ParallelUpload - auto multipart upload object
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - filename: the filename
// - contentType: the content type default(application/octet-stream)
// - args: the bucket name nil using default
// RETURNS:
// - *api.CompleteMultipartUploadResult: multipart upload result
// - error: nil if success otherwise the specific error
func (c *Client) ParallelUpload(bucket string, object string, filename string, contentType string, args *api.InitiateMultipartUploadArgs) (*api.CompleteMultipartUploadResult, error) {
initiateMultipartUploadResult, err := api.InitiateMultipartUpload(c, bucket, object, contentType, args)
if err != nil {
return nil, err
}
partEtags, err := c.parallelPartUpload(bucket, object, filename, initiateMultipartUploadResult.UploadId)
if err != nil {
c.AbortMultipartUpload(bucket, object, initiateMultipartUploadResult.UploadId)
return nil, err
}
completeMultipartUploadResult, err := c.CompleteMultipartUploadFromStruct(bucket, object, initiateMultipartUploadResult.UploadId, &api.CompleteMultipartUploadArgs{Parts: partEtags})
if err != nil {
c.AbortMultipartUpload(bucket, object, initiateMultipartUploadResult.UploadId)
return nil, err
}
return completeMultipartUploadResult, nil
}
// parallelPartUpload - single part upload
//
// PARAMS:
// - bucket: the bucket name
// - object: the object name
// - filename: the uploadId
// - uploadId: the uploadId
// RETURNS:
// - []api.UploadInfoType: multipart upload result
// - error: nil if success otherwise the specific error
func (c *Client) parallelPartUpload(bucket string, object string, filename string, uploadId string) ([]api.UploadInfoType, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
// 分块大小按MULTIPART_ALIGN=1MB对齐
partSize := (c.MultipartSize +
MULTIPART_ALIGN - 1) / MULTIPART_ALIGN * MULTIPART_ALIGN
// 获取文件大小并计算分块数目最大分块数MAX_PART_NUMBER=10000
fileInfo, _ := file.Stat()
fileSize := fileInfo.Size()
partNum := (fileSize + partSize - 1) / partSize
if partNum > MAX_PART_NUMBER { // 超过最大分块数,需调整分块大小
partSize = (fileSize + MAX_PART_NUMBER + 1) / MAX_PART_NUMBER
partSize = (partSize + MULTIPART_ALIGN - 1) / MULTIPART_ALIGN * MULTIPART_ALIGN
partNum = (fileSize + partSize - 1) / partSize
}
parallelChan := make(chan int, c.MaxParallel)
errChan := make(chan error, c.MaxParallel)
resultChan := make(chan api.UploadInfoType, partNum)
// 逐个分块上传
for i := int64(1); i <= partNum; i++ {
// 计算偏移offset和本次上传的大小uploadSize
uploadSize := partSize
offset := partSize * (i - 1)
left := fileSize - offset
if left < partSize {
uploadSize = left
}
// 创建指定偏移、指定大小的文件流
partBody, _ := bce.NewBodyFromSectionFile(file, offset, uploadSize)
select {
case err = <-errChan:
return nil, err
default:
select {
case err = <-errChan:
return nil, err
case parallelChan <- 1:
go c.singlePartUpload(bucket, object, uploadId, int(i), partBody, parallelChan, errChan, resultChan)
}
}
}
partEtags := make([]api.UploadInfoType, partNum)
for i := int64(0); i < partNum; i++ {
select {
case err := <-errChan:
return nil, err
case result := <-resultChan:
partEtags[result.PartNumber-1].PartNumber = result.PartNumber
partEtags[result.PartNumber-1].ETag = result.ETag
}
}
return partEtags, nil
}
// singlePartUpload - single part upload
//
// PARAMS:
// - pararelChan: the pararelChan
// - errChan: the error chan
// - result: the upload result chan
// - bucket: the bucket name
// - object: the object name
// - uploadId: the uploadId
// - partNumber: the part number of the object
// - content: the content of current part
func (c *Client) singlePartUpload(
bucket string, object string, uploadId string,
partNumber int, content *bce.Body,
parallelChan chan int, errChan chan error, result chan api.UploadInfoType) {
defer func() {
if r := recover(); r != nil {
log.Fatal("parallelPartUpload recovered in f:", r)
errChan <- errors.New("parallelPartUpload panic")
}
<-parallelChan
}()
var args api.UploadPartArgs
args.ContentMD5 = content.ContentMD5()
etag, err := api.UploadPart(c, bucket, object, uploadId, partNumber, content, &args)
if err != nil {
errChan <- err
log.Error("upload part fail,err:%v", err)
return
}
result <- api.UploadInfoType{PartNumber: partNumber, ETag: etag}
return
}
// ParallelCopy - auto multipart copy object
//
// PARAMS:
// - srcBucketName: the src bucket name
// - srcObjectName: the src object name
// - destBucketName: the dest bucket name
// - destObjectName: the dest object name
// - args: the copy args
// - srcClient: the src region client
// RETURNS:
// - *api.CompleteMultipartUploadResult: multipart upload result
// - error: nil if success otherwise the specific error
func (c *Client) ParallelCopy(srcBucketName string, srcObjectName string,
destBucketName string, destObjectName string,
args *api.MultiCopyObjectArgs, srcClient *Client) (*api.CompleteMultipartUploadResult, error) {
if srcClient == nil {
srcClient = c
}
objectMeta, err := srcClient.GetObjectMeta(srcBucketName, srcObjectName)
if err != nil {
return nil, err
}
initArgs := api.InitiateMultipartUploadArgs{
CacheControl: objectMeta.CacheControl,
ContentDisposition: objectMeta.ContentDisposition,
Expires: objectMeta.Expires,
StorageClass: objectMeta.StorageClass,
}
if args != nil {
if len(args.StorageClass) != 0 {
initArgs.StorageClass = args.StorageClass
}
}
initiateMultipartUploadResult, err := api.InitiateMultipartUpload(c, destBucketName, destObjectName, objectMeta.ContentType, &initArgs)
if err != nil {
return nil, err
}
source := fmt.Sprintf("/%s/%s", srcBucketName, srcObjectName)
partEtags, err := c.parallelPartCopy(*objectMeta, source, destBucketName, destObjectName, initiateMultipartUploadResult.UploadId)
if err != nil {
c.AbortMultipartUpload(destBucketName, destObjectName, initiateMultipartUploadResult.UploadId)
return nil, err
}
completeMultipartUploadResult, err := c.CompleteMultipartUploadFromStruct(destBucketName, destObjectName, initiateMultipartUploadResult.UploadId, &api.CompleteMultipartUploadArgs{Parts: partEtags})
if err != nil {
c.AbortMultipartUpload(destBucketName, destObjectName, initiateMultipartUploadResult.UploadId)
return nil, err
}
return completeMultipartUploadResult, nil
}
// parallelPartCopy - parallel part copy
//
// PARAMS:
// - srcMeta: the copy source object meta
// - source: the copy source
// - bucket: the dest bucket name
// - object: the dest object name
// - uploadId: the uploadId
// RETURNS:
// - []api.UploadInfoType: multipart upload result
// - error: nil if success otherwise the specific error
func (c *Client) parallelPartCopy(srcMeta api.GetObjectMetaResult, source string, bucket string, object string, uploadId string) ([]api.UploadInfoType, error) {
var err error
size := srcMeta.ContentLength
partSize := int64(DEFAULT_MULTIPART_SIZE)
if partSize*MAX_PART_NUMBER < size {
lowerLimit := int64(math.Ceil(float64(size) / MAX_PART_NUMBER))
partSize = int64(math.Ceil(float64(lowerLimit)/float64(partSize))) * partSize
}
partNum := (size + partSize - 1) / partSize
parallelChan := make(chan int, c.MaxParallel)
errChan := make(chan error, c.MaxParallel)
resultChan := make(chan api.UploadInfoType, partNum)
for i := int64(1); i <= partNum; i++ {
// 计算偏移offset和本次上传的大小uploadSize
uploadSize := partSize
offset := partSize * (i - 1)
left := size - offset
if left < partSize {
uploadSize = left
}
partCopyArgs := api.UploadPartCopyArgs{
SourceRange: fmt.Sprintf("bytes=%d-%d", (i-1)*partSize, (i-1)*partSize+uploadSize-1),
IfMatch: srcMeta.ETag,
}
select {
case err = <-errChan:
return nil, err
default:
select {
case err = <-errChan:
return nil, err
case parallelChan <- 1:
go c.singlePartCopy(source, bucket, object, uploadId, int(i), &partCopyArgs, parallelChan, errChan, resultChan)
}
}
}
partEtags := make([]api.UploadInfoType, partNum)
for i := int64(0); i < partNum; i++ {
select {
case err := <-errChan:
return nil, err
case result := <-resultChan:
partEtags[result.PartNumber-1].PartNumber = result.PartNumber
partEtags[result.PartNumber-1].ETag = result.ETag
}
}
return partEtags, nil
}
// singlePartCopy - single part copy
//
// PARAMS:
// - pararelChan: the pararelChan
// - errChan: the error chan
// - result: the upload result chan
// - source: the copy source
// - bucket: the bucket name
// - object: the object name
// - uploadId: the uploadId
// - partNumber: the part number of the object
// - args: the copy args
func (c *Client) singlePartCopy(source string, bucket string, object string, uploadId string,
partNumber int, args *api.UploadPartCopyArgs,
parallelChan chan int, errChan chan error, result chan api.UploadInfoType) {
defer func() {
if r := recover(); r != nil {
log.Fatal("parallelPartUpload recovered in f:", r)
errChan <- errors.New("parallelPartUpload panic")
}
<-parallelChan
}()
copyObjectResult, err := api.UploadPartCopy(c, bucket, object, source, uploadId, partNumber, args)
if err != nil {
errChan <- err
log.Error("upload part fail,err:%v", err)
return
}
result <- api.UploadInfoType{PartNumber: partNumber, ETag: copyObjectResult.ETag}
return
}
// PutSymlink - create symlink for exist target object
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the object
// - symlinkKey: the name of the symlink
// - symlinkArgs: the optional arguments
// RETURNS:
// - error: the put error if any occurs
func (c *Client) PutSymlink(bucket string, object string, symlinkKey string, symlinkArgs *api.PutSymlinkArgs) error {
return api.PutObjectSymlink(c, bucket, object, symlinkKey, symlinkArgs)
}
// PutSymlink - create symlink for exist target object
//
// PARAMS:
// - bucket: the name of the bucket
// - object: the name of the symlink
// RETURNS:
// - string: the target of the symlink
// - error: the put error if any occurs
func (c *Client) GetSymlink(bucket string, object string) (string, error) {
return api.GetObjectSymlink(c, bucket, object)
}
func (c *Client) PutBucketMirror(bucket string, putBucketMirrorArgs *api.PutBucketMirrorArgs) error {
return api.PutBucketMirror(c, bucket, putBucketMirrorArgs)
}
func (c *Client) GetBucketMirror(bucket string) (*api.PutBucketMirrorArgs, error) {
return api.GetBucketMirror(c, bucket)
}
func (c *Client) DeleteBucketMirror(bucket string) error {
return api.DeleteBucketMirror(c, bucket)
}