You need to enable JavaScript to run this app.
导航

TOS 使用 PreSignedURL 进行分片上传

最近更新时间2024.01.03 10:41:28

首次发布时间2023.09.14 16:08:45

本文介绍使用 PreSignedURL 进行分片上传的过程。

前言

TOS提供两种上传方式,简单上传跟分片上传,简单上传方式最大能够上传5GB的文件,所以如果对象大小超过5GB,需要使用分片上传实现。

使用分片上传,您可以将对象分成多个数据块(Part)分别上传,每个分片都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分片。如果其中任意分片上传失败,可以重新进行上传且不影响其他分片。上传完所有分片后,汇集所有分片并创建元数据。

分片上传优势:

  • 提高吞吐量 - 您可以并行上传分段以提高吞吐量。
  • 从网络问题中快速恢复 - 使用分片,可以将因网络问题导致的上传失败影响降至最低。
  • 暂停和恢复上传 - 您可以在一段时间内分别上传对象的分片。启用分片后,不存在过期期限;您需要显示完成或停止分片上传。

分片上传流程:

  • 初始化分片上传
  • 上传分片
  • 分片上传完成

预签名 URL:

可以使用预签名 URL 提供 TOS 桶中对象的限时访问权限。可以直接使用预签名 URL 来下载对象;还可以使用预签名 URL 来允许用户将特定对象上传到 TOS 桶。使用预签名 URL 不要求用户拥有 TOS 凭证或权限,并且在到期日期之前,可以多次使用预签名 URL。

本实验将实现使用预签名进行分段上传的过程。

关于实验
  • 预计部署时间:40分钟
  • 级别:中级
  • 相关产品:TOS
  • 受众: 通用
实验说明
  • 点击此链接登录控制台。

  • 如果您还没有账户,请点击此链接注册账户。

  • 使用GO、Postman 进行模拟。

实验步骤

一、安装Go SDK

您可以使用如下命令安装Go SDK。

go get -u github.com/volcengine/ve-tos-golang-sdk/v2

二、初始化分片上传

示例代码如下:

package main

import (
	"context"
	"fmt"
	"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 = "真实AK"
		secretKey = "真实SK"
		endpoint  = "tos-cn-beijing.volces.com"
		region    = "cn-beijing"
		// BucketName
		bucketName = "wanyix-1"
		// ObjectKey
		objectKey = "mul-lab-test"
		ctx       = context.Background()
	)
	// 初始化客户端
	client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
	checkErr(err)
	// 初始化分片,指定对象权限为私有,存储类型为低频并设置元数据信息

	createMultipartOutput, err := client.CreateMultipartUploadV2(ctx, &tos.CreateMultipartUploadV2Input{
		Bucket:       bucketName,
		Key:          objectKey,
		ACL:          enum.ACLPrivate,
		StorageClass: enum.StorageClassIa,
		Meta:         map[string]string{"key": "value"},
	})
	checkErr(err)
	//fmt.Println("CreateMultipartUploadV2 Request ID:", createMultipartOutput.RequestID)
	// 获取到分片上传 UploadID
	fmt.Println("CreateMultipartUploadV2 Upload ID:", createMultipartOutput.UploadID)

}

响应如下:

CreateMultipartUploadV2 Upload ID: 7443ad5cb011dd73cfd501db44a3ff10

完成后,可以拿到分片上传的ID。

三、生成各个分片的预签名URL,本实验模拟两个分片

package main

import (
	//"context"
	"fmt"
	"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
	"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
	_ "strings"
)

func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}
func main() {
	var (
		accessKey = "真实AK"
		secretKey = "真实SK"
		endpoint = "tos-cn-beijing.volces.com"
		region   = "cn-beijing"
	)
	client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
	checkErr(err)

	preinput := &tos.PreSignedURLInput{
		enum.HttpMethodPut,
		"wanyix-1",// 桶名
		"mul-lab-test",// 对象名
		3600,// 过期时间
		map[string]string{},
		map[string]string{"partNumber": "1", "uploadId": "7443ad5cb011dd73cfd501db44a3ff10"},// 各个分片数字及分片ID,uploadId 始终一致,partNumber 跟分片数量一致,如第一个分片,为1
		"",
	}

	get, err := client.PreSignedURL(preinput)

	fmt.Println(get.SignedUrl)

}

响应如下:

https://wanyix-1.tos-cn-beijing.volces.com/mul-lab-test?X-Tos-Algorithm=TOS4-HMAC-SHA256&X-Tos-Credential=AKLTN2QyZmNlZjE0NjM2NDUwOdslMDdmYTllZmJkOGFjYTU%2F20230815%2Fcn-beijing%2Ftos%2Frequest&X-Tos-Date=20230815T081810Z&X-Tos-Expires=3600&X-Tos-Signature=c949c66d5250ce1006ae4750902408814d57c664293dd642285caccc8ea34098&X-Tos-SignedHeaders=host&partNumber=2&uploadId=7443ad5cb011dd73cfd501db44a3ff10

四、使用Postman 模拟上传

使用PUT 方法,url 填入步骤三中预签名 URL,Body 处将要上传对象的分片导入。
结果如下:

alt

上传完成后,将每个分片的ETag 进行保存。

五、分片上传完成后,合并分片

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 = "真实AK"
		secretKey = "真实SK"
		endpoint  = "tos-cn-beijing.volces.com"
		region    = "cn-beijing"
		// 填写 BucketName
		bucketName = "wanyix-1"
		// 指定的 ObjectKey
		objectKey = "mul-lab-test"
		ctx       = context.Background()
	)
	// 初始化客户端
	client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
	checkErr(err)

	var parts []tos.UploadedPartV2

	parts = append(parts, tos.UploadedPartV2{PartNumber: 1, ETag: "141ab4936c1084e1d4edca2192a1d1ff"})
	parts = append(parts, tos.UploadedPartV2{PartNumber: 2, ETag: "141ab4936c1084e1d4edca2192a1d1ff"})
	completeOutput, err := client.CompleteMultipartUploadV2(ctx, &tos.CompleteMultipartUploadV2Input{
		Bucket:   bucketName,
		Key:      objectKey,
		UploadID: "7443ad5cb011dd73cfd501db33a3ff10",
		Parts:    parts,
	})
	checkErr(err)
	fmt.Println("CompleteMultipartUploadV2 Request ID:", completeOutput.RequestID)

}

响应如下:

CompleteMultipartUploadV2 Request ID: acd301db3897047164db3897-b55924b-1qVpVX-CoMU-cb-tos-front-azb-1

控制台进行验证:

alt

上传完成。

参考文档:
[1] TOS Go SDK
[2] 分片上传

如果您有其他问题,欢迎您联系火山引擎技术支持服务