全部文档
当前文档

暂无内容

如果没有找到您期望的内容,请尝试其他搜索词

文档中心

分块上传(Go)

最近更新时间: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)

以下代码为分块上传加密文件,加密类型为:使用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)

以下代码为分块上传加密文件,加密类型为:客户提供加密密钥的服务器端加密(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))
}

文档导读
纯净模式常规模式

纯净模式

点击可全屏预览文档内容
文档反馈