如果你对Gin和微服务有一定了解,看本文较容易。
执行命令:
go get github.com/qiniu/go-sdk/v7
Go SDK 的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access Key
和Secret Key
,这对密钥可以通过如下步骤获得:
准备好这四个基本配置,供后面使用:
SecretKey = your secretkey
AccessKey = your accesskey
Bucket = your bucket
Domain = your domain
由于proto文件是这样定义的:
message PublishRequest{
// @inject_tag: json:"data" form:"data"
bytes data = 1; // 视频数据
}
也就是说data数据是bytes类型,这意味着我们通过Gin从前端获取的视频要转化为字节数组,这样才能传给相应的微服务,然后对应的微服务实现视频上传。
下面是Gin的处理逻辑:
videoPb.PublishRequest和videoPb.PublishResponse就是你用proto文件生成对应的后缀为pb.go里面的东西。
func PublishHandler(ctx *gin.Context) {
var req videoPb.PublishRequest
//将获得的文件转为[]byte类型
data, err := ctx.FormFile("data")
if err != nil {
ctx.JSON(http.StatusInternalServerError, FailRequest(err.Error()))
}
file, err := data.Open()
defer file.Close()
if err != nil {
ctx.JSON(http.StatusInternalServerError, FailRequest(err.Error()))
}
// 使用缓冲区逐块读取文件内容并写入 req.Data
var buffer bytes.Buffer
_, err = io.Copy(&buffer, file)
if err != nil {
ctx.JSON(http.StatusInternalServerError, FailRequest(err.Error()))
return
}
req.Data = buffer.Bytes()
//这里表示远程调用相关的微服务
res, err := Publish(ctx, &req)
if err != nil {
ctx.JSON(http.StatusInternalServerError, FailRequest(err.Error()))
return
}
ctx.JSON(http.StatusOK, gin.H{
"status_code": res.StatusCode,
"status_msg": res.StatusMsg,
})
}
func Publish(ctx context.Context, req *videoPb.PublishRequest) (res *videoPb.PublishResponse, err error) {
res, err = VideoService.Publish(ctx, req)
if err != nil {
return
}
return
}
func FailRequest(StatusMsg string) gin.H {
return gin.H{
"status_code": 1,
"status_msg": StatusMsg,
}
}
PublishHandler
函数:这是一个Gin路由处理函数,用于接收前端传来的视频数据并处理上传逻辑。ctx.FormFile("data")
从请求中获取上传的文件。data.Open()
打开文件。req.Data
字段,将视频数据存储为字节数组。videoPb.PublishRequest
实例 req
,其中已经存储了上传的视频数据。Publish
函数,并将 ctx
和 req
作为参数传递给该函数。下面是对应的微服务处理逻辑:
func (v *VideoSrv) Publish(ctx context.Context, req *videoPb.PublishRequest, res *videoPb.PublishResponse) error {
data := req.Data
VideoUrl, err := util.UploadVideo(data)
if err != nil {
PublishResponseData(res, 1, "发布失败")
return err
}
PublishResponseData(res, 0, "发布成功")
return nil
}
func UploadVideo(data []byte) (VideoUrl string, err error) {
SecretKey = your secretkey
AccessKey = your accesskey
Bucket = your bucket
Domain = your domain
size := int64(len(data))
//也可以用时间戳,这里用的uuid
key := fmt.Sprintf("%s.mp4", GenerateUUID())
putPolicy := storage.PutPolicy{
Scope: fmt.Sprintf("%s:%s", Bucket, key),
}
mac := qbox.NewMac(AccessKey, SecretKey)
upToken := putPolicy.UploadToken(mac)
cfg := storage.Config{}
uploader := storage.NewFormUploader(&cfg)
ret := storage.PutRet{}
//可选配置
putExtra := storage.PutExtra{
Params: map[string]string{
"x:name": "github logo",
},
}
err = uploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(data), size, &putExtra)
if err != nil {
return "", err
}
return fmt.Sprintf("%s/%s", Domain, ret.Key), nil
}
func PublishResponseData(res *videoPb.PublishResponse, StatusCode int32, StatusMsg string) {
res.StatusCode = StatusCode
res.StatusMsg = StatusMsg
}
func GenerateUUID() string {
id := uuid.New()
return id.String()
}
Publish
函数:这是微服务中的一个处理函数,用于接收上传请求并进行视频上传逻辑。req.Data
中获取视频数据。util.UploadVideo
函数将视频数据上传到云存储服务中(这里使用七牛云存储)。videoPb.PublishResponse
实例中。PublishResponseData
函数:用于填充响应对象的状态码和状态消息。GenerateUUID
函数:生成唯一标识符,通常用于生成上传文件的唯一键。