func (u *Uploader) UploadWithContext(ctx context.Context, fd io.Reader, objectKey string) error {
	logger := log.FromContext(ctx)
	length, err := getFileSize(fd)
	if err != nil {
		logger.Error("get file size", zap.Error(err))
		return err
	}
	if length < int64(smallestPartSize) {
		_, err := u.bucket.PutObjectWithContext(ctx, objectKey, &service.PutObjectInput{Body: fd})
		if err != nil {
			logger.Error("auto switch to put object", zap.Error(err))
			return err
		}
		return nil
	}
	if u.partSize < smallestPartSize {
		logger.Error("part size too small")
		return errors.New("the part size is too small")
	}
	uploadID, err := u.init(ctx, objectKey)
	if err != nil {
		logger.Error("init multipart upload", zap.Error(err))
		return err
	}
	partNumbers, err := u.upload(ctx, fd, uploadID, objectKey)
	if err != nil {
		logger.Error("upload part",
			zap.String("upload id", *uploadID), zap.String("key", objectKey), zap.Error(err))
		return err
	}
	err = u.complete(ctx, objectKey, uploadID, partNumbers)
	if err != nil {
		logger.Error("complete upload",
			zap.String("upload id", *uploadID), zap.String("key", objectKey), zap.Error(err))
		return err
	}
	return nil
}
UploadWithContext add support for context
package upload
import (
	"context"
	"errors"
	"io"
	"go.uber.org/zap"
	"github.com/qingstor/qingstor-sdk-go/v4/log"
	"github.com/qingstor/qingstor-sdk-go/v4/service"
)
type Uploader struct {
	bucket   *service.Bucket
	partSize int
}
const smallestPartSize int = 1024 * 1024 * 4
func Init(bucket *service.Bucket, partSize int) *Uploader {
	return &Uploader{
		bucket:   bucket,
		partSize: partSize,
	}
}
func (u *Uploader) Upload(fd io.Reader, objectKey string) error {
	return u.UploadWithContext(context.Background(), fd, objectKey)
}