普通上传是指通过 PutObjectV2 方法上传单个对象(Object),支持上传字符串(字符流)、上传 Bytes(Bytes 流)、上传网络流和上传本地文件四种形式。
tos:PutObject
权限,具体操作,请参见权限配置指南。您可以通过以下示例代码,使用 PutObjectV2 接口,上传字符串数据到 TOS 指定 example_dir
目录下的 example.txt
文件。
package main
import (
"context"
"fmt"
"strings"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
// 将字符串 “Hello TOS” 上传到指定 example_dir 目录下的 example.txt
body := strings.NewReader("Hello TOS")
output, err := client.PutObjectV2(ctx, &tos.PutObjectV2Input{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
},
Content: body,
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
您可以通过以下示例代码,使用 PutObjectV2 接口上传网络流数据到 TOS 指定 example_dir
目录下的 example.txt
文件。
package main
import (
"context"
"fmt"
"net/http"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
// 从网络流中获取数据
res, _ := http.Get("https://www.volcengine.com/")
defer res.Body.Close()
output, err := client.PutObjectV2(ctx, &tos.PutObjectV2Input{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
},
Content: res.Body,
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
您可以通过以下示例代码,使用 PutObjectV2 接口,将指定路径上的文件上传到 TOS 指定 example_dir
目录下的 example.txt
文件。
package main
import (
"context"
"fmt"
"os"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
fileName = "/usr/local/test.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
// 读取本地文件数据
f, err := os.Open("./example.txt")
if err != nil {
panic(err)
}
defer f.Close()
output, err := client.PutObjectV2(ctx, &tos.PutObjectV2Input{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
},
Content: f,
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
您可以通过以下示例代码,使用 PutObjectFromFile 接口,通过指定文件路径将文件上传到 TOS 指定 example_dir
目录下的 example.txt
文件。
package main
import (
"context"
"fmt"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
// 直接使用文件路径上传文件
output, err := client.PutObjectFromFile(ctx, &tos.PutObjectFromFileInput{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
},
FilePath: "./example.txt",
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
您可以通过以下示例代码,使用 PutObjectV2 接口,上传字符串数据到指定 example_dir
目录下的 example.txt
文件,上传时指定对象存储类型为低频存储,权限为私有同时设置上传文件元数据信息。
package main
import (
"context"
"fmt"
"strings"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
// 将字符串 “Hello TOS” 上传到指定 example_dir 目录下的 example.txt
body := strings.NewReader("Hello TOS")
output, err := client.PutObjectV2(ctx, &tos.PutObjectV2Input{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
// 指定存储类型为低频存储
StorageClass: enum.StorageClassIa,
// 指定对象权限为私有
ACL: enum.ACLPrivate,
// 用户自定义元数据信息
Meta: map[string]string{"key": "value"},
},
Content: body,
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
上传时可通过实现 tos.DataTransferStatusChange 接口接收上传进度,代码示例如下。
package main
import (
"context"
"fmt"
"strings"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
// 自定义进度回调,需要实现 tos.DataTransferStatusChange 接口
type listener struct {
}
func (l *listener) DataTransferStatusChange(event *tos.DataTransferStatus) {
switch event.Type {
case enum.DataTransferStarted:
fmt.Println("Data transfer started")
case enum.DataTransferRW:
// Chunk 模式下 TotalBytes 值为 -1
if event.TotalBytes != -1 {
fmt.Printf("Once Read:%d,ConsumerBytes/TotalBytes: %d/%d,%d%%\n", event.RWOnceBytes, event.ConsumedBytes, event.TotalBytes, event.ConsumedBytes*100/event.TotalBytes)
} else {
fmt.Printf("Once Read:%d,ConsumerBytes:%d\n", event.RWOnceBytes, event.ConsumedBytes)
}
case enum.DataTransferSucceed:
fmt.Printf("Data Transfer Succeed, ConsumerBytes/TotalBytes: %d/%d,%d%%\n", event.ConsumedBytes, event.TotalBytes, event.ConsumedBytes*100/event.TotalBytes)
case enum.DataTransferFailed:
fmt.Printf("Data Transfer Failed\n")
}
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
// 将字符串 “Hello TOS” 上传到指定 example_dir 目录下的 example.txt
body := strings.NewReader("Hello TOS")
output, err := client.PutObjectV2(ctx, &tos.PutObjectV2Input{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
// 通过自定义方式设置回调函数查看上传进度
DataTransferListener: &listener{},
},
Content: body,
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
上传对象时可以通过客户端使用 tos.RateLimiter 接口对上传数据所占用的带宽进行限制,代码如下所示。
package main
import (
"context"
"fmt"
"strings"
"sync"
"time"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
)
func checkErr(err error) {
if err != nil {
if serverErr, ok := err.(*tos.TosServerError); ok {
fmt.Println("Error:", serverErr.Error())
fmt.Println("Request ID:", serverErr.RequestID)
fmt.Println("Response Status Code:", serverErr.StatusCode)
fmt.Println("Response Header:", serverErr.Header)
fmt.Println("Response Err Code:", serverErr.Code)
fmt.Println("Response Err Msg:", serverErr.Message)
} else if clientErr, ok := err.(*tos.TosClientError); ok {
fmt.Println("Error:", clientErr.Error())
fmt.Println("Client Cause Err:", clientErr.Cause.Error())
} else {
fmt.Println("Error:", err)
}
panic(err)
}
}
type rateLimit struct {
rate int64
capacity int64
currentAmount int64
sync.Mutex
lastConsumeTime time.Time
}
func NewDefaultRateLimit(rate int64, capacity int64) tos.RateLimiter {
return &rateLimit{
rate: rate,
capacity: capacity,
lastConsumeTime: time.Now(),
currentAmount: capacity,
Mutex: sync.Mutex{},
}
}
func (d *rateLimit) Acquire(want int64) (ok bool, timeToWait time.Duration) {
d.Lock()
defer d.Unlock()
if want > d.capacity {
want = d.capacity
}
increment := int64(time.Now().Sub(d.lastConsumeTime).Seconds() * float64(d.rate))
if increment+d.currentAmount > d.capacity {
d.currentAmount = d.capacity
} else {
d.currentAmount += increment
}
if want > d.currentAmount {
timeToWaitSec := float64(want-d.currentAmount) / float64(d.rate)
return false, time.Duration(timeToWaitSec * float64(time.Second))
}
d.lastConsumeTime = time.Now()
d.currentAmount -= want
return true, 0
}
func main() {
var (
accessKey = os.Getenv("TOS_ACCESS_KEY")
secretKey = os.Getenv("TOS_SECRET_KEY")
// Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com
endpoint = "https://tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写 BucketName
bucketName = "*** Provide your bucket name ***"
// 将文件上传到 example_dir 目录下的 example.txt 文件
objectKey = "example_dir/example.txt"
ctx = context.Background()
)
// 初始化客户端
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
checkErr(err)
body := strings.NewReader("Hello TOS")
rateLimit1M := 1024 * 1024
// 上传对象并在客户端限制上传速度为 1M/s
output, err := client.PutObjectV2(ctx, &tos.PutObjectV2Input{
PutObjectBasicInput: tos.PutObjectBasicInput{
Bucket: bucketName,
Key: objectKey,
RateLimiter: NewDefaultRateLimit(int64(rateLimit1M), int64(rateLimit1M)),
},
Content: body,
})
checkErr(err)
fmt.Println("PutObjectV2 Request ID:", output.RequestID)
}
关于上传对象的 API 文档,请参见 PutObject。