最近更新时间:2024-11-11 19:47:34
分块上传分为以下三个步骤:
上传中,你可以使用Abort Multipart Upload取消上传,或者List Parts查看上传的分块。或者List Multipart Uploads查看当前的bucket下有多少个uploadid。
以下代码为分块上传文件:
package main
import (
"bytes"
"fmt"
"github.com/ks3sdklib/aws-sdk-go/aws"
"github.com/ks3sdklib/aws-sdk-go/aws/awsutil"
"github.com/ks3sdklib/aws-sdk-go/aws/credentials"
"github.com/ks3sdklib/aws-sdk-go/service/s3"
"io"
"os"
)
func main() {
// 创建访问凭证,请将<AccessKeyID>与<SecretAccessKey>替换成真正的值
cre := credentials.NewStaticCredentials("<AccessKeyID>", "<SecretAccessKey>", "")
// 创建S3Client,更多配置项请查看Go-SDK初始化文档
client := s3.New(&aws.Config{
Credentials: cre, // 访问凭证
Region: "BEIJING", // 填写您的Region
Endpoint: "ks3-cn-beijing.ksyuncs.com", // 填写您的Endpoint
})
// 填写存储空间名称
bucket := "<bucket_name>"
// 填写对象的Key
key := "<object_key>"
// 填写上传文件路径
filePath := "/Users/test/demo.txt"
// 初始化分块上传
// 此操作将启动一个分块上传任务并返回upload ID。在一个确定的分块上传任务中,upload ID用于关联所有分块。
// 连续分块上传请求中的upload ID由用户指定。在Complete Multipart Upload 和 Abort Multipart Upload请求中同样包含upload ID。
// 关于请求签名的问题,分块上传为一系列的请求(初始化分块上传,上传块,完成分块上传,终止分块上传),用户启动任务,发送一个或多个分块,最终完成任务。用户需要对每一个请求单独签名。
// 注意: 当你启动分块上传后,并开始上传分块,你必须完成或者放弃上传任务,才能终止因为存储造成的收费。
initRet, err := client.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
ACL: aws.String(s3.ACLPublicRead), // 访问权限,非必填
ContentType: aws.String("application/octet-stream"), // 文件类型,非必填
})
if err != nil {
panic(err)
}
// 获取分块上传Id
uploadId := *initRet.UploadID
fmt.Println("uploadId:", uploadId)
// 打开文件
file, err := os.Open(filePath)
if err != nil {
panic(err)
}
defer file.Close()
var partNum int64 = 1
// 待合并分块
var compParts []*s3.CompletedPart
// 缓冲区,分块大小为5MB
buffer := make([]byte, 5*1024*1024)
for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
panic(err)
} else if n == 0 {
break
} else {
// 上传单个分块
// 在你发送一个启动请求后,KS3会给你一个唯一的upload ID。每次上传块时,都需要将上传ID包含在请求中。
// 块的数量可以是1到10,000中的任意一个(包含1和10,000)。
// 块序号用于标识一个块以及其在对象创建时的位置。如果你上传一个新的块,使用之前已经使用的序列号,那么之前的那个块将会被覆盖。
// 除最后一个块外,其余块的大小均要求大于或等于100KB,单个块的大小不能超过5GB。
// 如果不符合上述要求,会返回413状态码。
// 为了保证数据在传输过程中没有损坏,请使用 Content-MD5 头部。当使用此头部时,KS3会自动计算出MD5,并根据用户提供的MD5进行校验,如果不匹配,将会返回错误信息。
resp, err := client.UploadPart(&s3.UploadPartInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
PartNumber: aws.Long(partNum), // 分块序号,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
Body: bytes.NewReader(buffer[:n]), // 分块内容,必填
})
if err != nil {
panic(err)
}
// 已上传分块序号和etag信息,用于合并分块
compParts = append(compParts, &s3.CompletedPart{PartNumber: aws.Long(partNum), ETag: resp.ETag})
fmt.Printf("已上传第%d块,etag:%s\n", partNum, *resp.ETag)
partNum++
}
}
// 完成分块上传(合并分块)
// 用户启动一个分块上传任务后,会使用 Upload Parts 接口上传所有的块。成功上传所有相关块之后,用户需要调用此接口来完成分块上传。
// 收到完成请求后,KS3将会根据块序号将所有的块组装起来创建一个新的对象。
// 在用户的完成任务请求中需要用户提供分块列表,由于KS3将会按照列表将所有块连接起来,所以要求用户保证所有的块已经完成上传。
// 对于分块列表中的每一个块,用户需要在上传块时添加块序号以及对象的 ETag 头部,KS3则会在块完成上传后回复完成响应。
compRet, _ := client.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
MultipartUpload: &s3.CompletedMultipartUpload{
Parts: compParts, // 已上传分块序号和etag信息,用于合并分块,必填
},
})
fmt.Println("结果:\n", awsutil.StringValue(compRet))
}
以下代码为分块上传加密文件,加密类型为:使用KS3托管密钥的服务器端加密(SSE-S3)。
package main
import (
"bytes"
"fmt"
"github.com/ks3sdklib/aws-sdk-go/aws"
"github.com/ks3sdklib/aws-sdk-go/aws/awsutil"
"github.com/ks3sdklib/aws-sdk-go/aws/credentials"
"github.com/ks3sdklib/aws-sdk-go/service/s3"
"io"
"os"
)
func main() {
// 创建访问凭证,请将<AccessKeyID>与<SecretAccessKey>替换成真正的值
cre := credentials.NewStaticCredentials("<AccessKeyID>", "<SecretAccessKey>", "")
// 创建S3Client,更多配置项请查看Go-SDK初始化文档
client := s3.New(&aws.Config{
Credentials: cre, // 访问凭证
Region: "BEIJING", // 填写您的Region
Endpoint: "ks3-cn-beijing.ksyuncs.com", // 填写您的Endpoint
})
// 填写存储空间名称
bucket := "<bucket_name>"
// 填写对象的Key
key := "<object_key>"
// 填写上传文件路径
filePath := "/Users/test/demo.txt"
// 初始化分块上传,使用KS3托管密钥的服务器端加密 (SSE-S3)
initRet, err := client.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
ServerSideEncryption: aws.String("AES256"), // 使用KS3托管密钥的服务器端加密,合法值:AES256
})
if err != nil {
panic(err)
}
// 获取分块上传Id
uploadId := *initRet.UploadID
fmt.Println("uploadId:", uploadId)
// 打开文件
file, err := os.Open(filePath)
if err != nil {
panic(err)
}
defer file.Close()
var partNum int64 = 1
// 待合并分块
var compParts []*s3.CompletedPart
// 缓冲区,分块大小为5MB
buffer := make([]byte, 5*1024*1024)
for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
panic(err)
} else if n == 0 {
break
} else {
// 上传单个分块
resp, err := client.UploadPart(&s3.UploadPartInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
PartNumber: aws.Long(partNum), // 分块序号,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
Body: bytes.NewReader(buffer[:n]), // 分块内容,必填
})
if err != nil {
panic(err)
}
// 已上传分块序号和etag信息,用于合并分块
compParts = append(compParts, &s3.CompletedPart{PartNumber: aws.Long(partNum), ETag: resp.ETag})
fmt.Printf("已上传第%d块,etag:%s\n", partNum, *resp.ETag)
partNum++
}
}
// 完成分块上传(合并分块)
compRet, _ := client.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
MultipartUpload: &s3.CompletedMultipartUpload{
Parts: compParts, // 已上传分块序号和etag信息,用于合并分块,必填
},
})
fmt.Println("结果:\n", awsutil.StringValue(compRet))
}
以下代码为分块上传加密文件,加密类型为:客户提供加密密钥的服务器端加密(SSE-C)。
package main
import (
"bytes"
"fmt"
"github.com/ks3sdklib/aws-sdk-go/aws"
"github.com/ks3sdklib/aws-sdk-go/aws/awsutil"
"github.com/ks3sdklib/aws-sdk-go/aws/credentials"
"github.com/ks3sdklib/aws-sdk-go/service/s3"
"io"
"os"
)
func main() {
// 创建访问凭证,请将<AccessKeyID>与<SecretAccessKey>替换成真正的值
cre := credentials.NewStaticCredentials("<AccessKeyID>", "<SecretAccessKey>", "")
// 创建S3Client,更多配置项请查看Go-SDK初始化文档
client := s3.New(&aws.Config{
Credentials: cre, // 访问凭证
Region: "BEIJING", // 填写您的Region
Endpoint: "ks3-cn-beijing.ksyuncs.com", // 填写您的Endpoint
})
// 填写存储空间名称
bucket := "<bucket_name>"
// 填写对象的Key
key := "<object_key>"
// 填写上传文件路径
filePath := "/Users/test/demo.txt"
// 填写您用于加密的密钥,密钥长度支持16/24/32位
SSECustomerKey := "<encryption_key>"
// 初始化分块上传,使用客户提供的加密密钥的服务器端加密(SSE-C)
initRet, err := client.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
SSECustomerAlgorithm: aws.String("AES256"), // 客户端提供的加密算法,合法值:AES256
SSECustomerKey: aws.String(s3.GetBase64Str(SSECustomerKey)), // 客户端提供的加密密钥进行Base64编码后的值
SSECustomerKeyMD5: aws.String(s3.GetBase64MD5Str(SSECustomerKey)), // 客户端提供的通过BASE64编码的通过128位MD5加密的密钥的MD5值
})
if err != nil {
panic(err)
}
// 获取分块上传Id
uploadId := *initRet.UploadID
fmt.Println("uploadId:", uploadId)
// 打开文件
file, err := os.Open(filePath)
if err != nil {
panic(err)
}
defer file.Close()
var partNum int64 = 1
// 待合并分块
var compParts []*s3.CompletedPart
// 缓冲区,分块大小为5MB
buffer := make([]byte, 5*1024*1024)
for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
panic(err)
} else if n == 0 {
break
} else {
// 上传单个分块,使用客户提供的加密密钥的服务器端加密(SSE-C)
resp, err := client.UploadPart(&s3.UploadPartInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
PartNumber: aws.Long(partNum), // 分块序号,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
Body: bytes.NewReader(buffer[:n]), // 分块内容,必填
SSECustomerAlgorithm: aws.String("AES256"), // 客户端提供的加密算法,合法值:AES256
SSECustomerKey: aws.String(s3.GetBase64Str(SSECustomerKey)), // 客户端提供的加密密钥进行Base64编码后的值
SSECustomerKeyMD5: aws.String(s3.GetBase64MD5Str(SSECustomerKey)), // 客户端提供的通过BASE64编码的通过128位MD5加密的密钥的MD5值
})
if err != nil {
panic(err)
}
// 已上传分块序号和etag信息,用于合并分块
compParts = append(compParts, &s3.CompletedPart{PartNumber: aws.Long(partNum), ETag: resp.ETag})
fmt.Printf("已上传第%d块,etag:%s\n", partNum, *resp.ETag)
partNum++
}
}
// 完成分块上传(合并分块)
compRet, _ := client.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
MultipartUpload: &s3.CompletedMultipartUpload{
Parts: compParts, // 已上传分块序号和etag信息,用于合并分块,必填
},
})
fmt.Println("结果:\n", awsutil.StringValue(compRet))
}
package main
import (
"bytes"
"fmt"
"github.com/ks3sdklib/aws-sdk-go/aws"
"github.com/ks3sdklib/aws-sdk-go/aws/awsutil"
"github.com/ks3sdklib/aws-sdk-go/aws/credentials"
"github.com/ks3sdklib/aws-sdk-go/service/s3"
"io"
"net/http"
"os"
"strconv"
)
func main() {
// 创建访问凭证,请将<AccessKeyID>与<SecretAccessKey>替换成真正的值
cre := credentials.NewStaticCredentials("<AccessKeyID>", "<SecretAccessKey>", "")
// 创建S3Client,更多配置项请查看Go-SDK初始化文档
client := s3.New(&aws.Config{
Credentials: cre, // 访问凭证
Region: "BEIJING", // 填写您的Region
Endpoint: "ks3-cn-beijing.ksyuncs.com", // 填写您的Endpoint
})
// 填写存储空间名称
bucket := "<bucket_name>"
// 填写对象的Key
key := "<object_key>"
// 填写上传文件路径
filePath := "/Users/test/demo.txt"
// 初始化分块上传
initRet, err := client.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
})
if err != nil {
panic(err)
}
// 获取分块上传Id
uploadId := *initRet.UploadID
fmt.Println("uploadId:", uploadId)
// 打开文件
file, err := os.Open(filePath)
if err != nil {
panic(err)
}
defer file.Close()
var partNum int64 = 1
// 待合并分块
var compParts []*s3.CompletedPart
// 缓冲区,分块大小为5MB
buffer := make([]byte, 5*1024*1024)
for {
n, err := file.Read(buffer)
if err != nil && err != io.EOF {
panic(err)
} else if n == 0 {
break
} else {
// 生成上传单个分块外链
url, err := client.GeneratePresignedUrl(&s3.GeneratePresignedUrlInput{
HTTPMethod: s3.PUT, // 请求方法,可选值有 PUT, GET, DELETE, HEAD, POST,必填
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
Expires: 3600, // 过期时间,例如,3600(表示1小时),必填
Parameters: map[string]*string{
"partNumber": aws.String(strconv.Itoa(int(partNum))), // 分块序号,必填
"uploadId": aws.String(uploadId), // 分块上传ID,必填
},
})
if err != nil {
panic(err)
}
fmt.Printf("已生成第%d块上传外链,url:%s\n", partNum, url)
// 上传单个分块,构造PUT请求
request, err := http.NewRequest("PUT", url, bytes.NewReader(buffer[:n]))
if err != nil {
panic(err)
}
// 发送请求
resp, err := http.DefaultClient.Do(request)
if err != nil {
panic(err)
}
if resp.StatusCode != 200 {
panic("上传失败")
}
// 已上传分块序号和etag信息,用于合并分块
compParts = append(compParts, &s3.CompletedPart{PartNumber: aws.Long(partNum), ETag: aws.String(resp.Header.Get("ETag"))})
fmt.Printf("已上传第%d块,etag:%s\n", partNum, resp.Header.Get("ETag"))
partNum++
}
}
// 完成分块上传(合并分块)
compRet, _ := client.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{
Bucket: aws.String(bucket), // 存储空间名称,必填
Key: aws.String(key), // 对象的key,必填
UploadID: aws.String(uploadId), // 分块上传ID,必填
MultipartUpload: &s3.CompletedMultipartUpload{
Parts: compParts, // 已上传分块序号和etag信息,用于合并分块,必填
},
})
fmt.Println("结果:\n", awsutil.StringValue(compRet))
}
纯净模式