这是我参与「第三届青训营 -后端场」笔记创作活动的的第 1 篇笔记。
前言
在看到项目文档之前,就已经考虑好了将视频保存在对象存储中而不是本地的方案。实际落地也没有遇到很多困难,且当对aws-sdk的一次简单了解吧。
什么是对象存储?
顾名思义,就是基于对象的存储。 和传统的关系型数据库不同的是,对象存储通常用于保存大量的非结构化数据,用简单的话来说,我们日常生活中生成的照片、视频、音频、文档等都属于非结构化数据。这些类型的文件都适合保存在对象存储中。
为什么使用aws-sdk?
在对象存储的行业中,aws-s3为事实标准,这意味着几乎所有的云厂商的对象存储都支持aws-s3的接口协议。无论哪个厂商的对象存储都可以直接使用aws-sdk进行操作,开发者不需要额外去学习新的文档,既有的代码在迁移到其他厂商以后依然可以直接使用。
创建Bucket
这里以腾讯云cos进行举例。
存储桶列表 - 对象存储 - 控制台 (tencent.com)
点击创建存储桶。
按照以下配置创建,需要注意的是由于我们的视频需要通过demo抖音客户端打开,因此访问权限选择公有读私有写。 创建完成即可使用了。对象存储的常规操作这里不做介绍。这里记下bucket名称和访问域名即可。
接下来在访问密钥 - 控制台 (tencent.com)中获取aws-sdk需要使用的accesskey和secretkey,在腾讯云中,SecretId就是accesskey。
使用aws-sdk将视频上传到bucket中
首先安装aws-sdk相关的package。
$ go get github.com/aws/aws-sdk-go-v2/aws
$ go get github.com/aws/aws-sdk-go-v2/config
$ go get github.com/aws/aws-sdk-go-v2/service/dynamodb
根据以上的信息,我们创建一个s3客户端。
package s3
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
awscfg "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/s3"
)
const (
endpoint = "https://cos.ap-guangzhou.myqcloud.com"
accesskey = "your access key"
secretkey = "your secret key"
bucketName = "your bucket"
region = "ap-guangzhou"
)
func NewS3Client() *s3.Client {
customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{
URL: endpoint,
SigningRegion: region,
}, nil
}) // 将endpoint设置为自己的endpoint
cfg, err := awscfg.LoadDefaultConfig(context.TODO(), awscfg.WithEndpointResolverWithOptions(customResolver))
if err != nil {
panic(err)
}
cfg.Region = region
cfg.Credentials = aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(accesskey, secretkey, ""))
// 设定accesskey和secretkey
client := s3.NewFromConfig(cfg)
// 创建s3客户端
return client
}
这个返回的s3.client就是我们执行上传操作的对象了。我们以后的操作都会使用这个对象下的方法。
上传视频我们使用PutObject方法,我们需要构造这个方法下所需的结构体。
func main() {
filepath := "./test.mp4"
file, err := os.Open("./test.mp4") //打开文件
if err != nil {
panic(err)
}
s3c := NewS3Client()
_, err = s3c.PutObject(context.TODO(), &s3.PutObjectInput{
Bucket: aws.String(bucketName),
//该field的类型为*string,可以用aws自带的aws.string进行转换
Key: aws.String(filepath),
Body: file,
ContentType: aws.String("video/mp4"),
}) //上传文件
if err != nil {
fmt.Printf("upload video to s3 failed: %s", err.Error())
return
}
fmt.Printf("upload video to s3 success: %s", filepath)
}
我们最终是要将上传的视频的url保存到数据库中的,在上传前后我们都可以用PreSign来直接获取对应对象的url。
func getobjecturl() {
s3c := NewS3Client()
ps3 := s3.NewPresignClient(s3c)
pr, err := ps3.PresignGetObject(context.TODO(), &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String("test.mp4"),
})
if err != nil {
fmt.Printf("get presign url failed: %s", err.Error())
return
}
playurl := strings.Replace(pr.URL, "http://", "https://", 1)
fmt.Printf("get presign url success: %s", playurl)
}
通过以上的实现,你就能做到将视频保存到对象存储中了。