基于华为云obs预签名URL实现大文件分段上传

举报
wuwenrefeng 发表于 2022/01/27 22:00:06 2022/01/27
【摘要】 基于华为云obs预签名URL实现大文件分段上传

预签名URL前端直传的限制:单次上传对象大小范围是[0, 5GB],如果需要上传超过5GB的大文件,需要通过多段操作来分段上传。

多段上传前后端交互流程:

前端文件分段

后端分段实现

// 多段上传-初始化(POST)
func InitiateMultipartUpload(key string) (uploadId string, err error) {
        object := getObsClient()
        input := &obs.CreateSignedUrlInput{}
        input.Method = obs.HttpMethodPost
        input.Key = key
        input.Bucket = global.Config.OBSBucketName
        input.Expires = global.Config.OBSExpires
        input.SubResource = obs.SubResourceUploads
        output, err := object.CreateSignedUrl(input)
        if err != nil {
                logrus.Errorf("创建预签名URL时发生错误,err:%+v\n", err)
                return "", err
        }
        outputInit, err := object.InitiateMultipartUploadWithSignedUrl(output.SignedUrl, output.ActualSignedRequestHeaders)
        if err != nil {
                logrus.Errorf("初始化分传段任务时发生错误,err:%+v\n", err)
                return "", err
        }
        return outputInit.UploadId, nil
}
// 多段上传-段上传(PUT)
func UploadPartWithPartNumber(key string, uploadId string, partNumber string) (string, error) {
        object := getObsClient()
        input := &obs.CreateSignedUrlInput{}
        input.Method = obs.HttpMethodPut
        input.Key = key
        input.Bucket = global.Config.OBSBucketName
        input.Expires = global.Config.OBSExpires
        input.QueryParams = make(map[string]string)
        input.QueryParams["uploadId"] = uploadId
        input.QueryParams["partNumber"] = partNumber
        output, err := object.CreateSignedUrl(input)
        if err != nil {
                logrus.Errorf("UploadPartWithPartNum: 多段上传时发生错误,err:%+v\n", err)
                return "", err
        }
        return output.SignedUrl, nil
}
type ObsPart struct {
        PartNumber int
        ETag       string
}
// 多段上传-合并段
func CompleteMultipartUpload(key string, uploadId string, parts []ObsPart) error {
        object := getObsClient()
        input := &obs.CompleteMultipartUploadInput{}
        input.Key = key
        input.Bucket = global.Config.OBSBucketName
        input.UploadId = uploadId
        inputParts := make([]obs.Part, len(parts))
        for i, v := range parts {
                p := inputParts[i]
                p.PartNumber = v.PartNumber
                p.ETag = v.ETag
                inputParts[i] = p
        }
        input.Parts = inputParts
        output, err := object.CompleteMultipartUpload(input)
        if err != nil {
                logrus.Errorf("CompleteMultipartUpload: 多段上传-合并段时发生错误,err:%+v\n", err)
                logrus.Printf("output: %+v", output)
                if obsError, ok := err.(obs.ObsError); ok {
                        logrus.Println(obsError.Code)
                        logrus.Println(obsError.Message)
                } else {
                        logrus.Println(err)
                }
                return err
        }
        return nil
}

注意:前后端分段计算方式要保持一致,即分段大小统一。

ISSUE:

  1. Error code: EntityTooSmall
  • Description: Your proposed upload is smaller than the minimum allowed object size. Each part must be at least 5 MB in size, except the last part.
  • 400 Bad Request

解决方案:分段上传时保证每段大小至少是5MB。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。