如果你对Gin和微服务有一定了解,看本文较容易。
安装
执行命令:
1
   | go get github.com/qiniu/go-sdk/v7
   | 
 
获取凭证
Go SDK 的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access Key和Secret Key,这对密钥可以通过如下步骤获得:
- 点击注册🔗开通七牛开发者帐号
 
- 如果已有账号,直接登录七牛开发者后台,点击这里🔗查看 Access Key 和 Secret Key
 


准备好这四个基本配置,供后面使用:
SecretKey = your secretkey
AccessKey = your accesskey
Bucket = your bucket
Domain = your domain
Gin处理
由于proto文件是这样定义的:
1 2 3 4
   | message PublishRequest{      bytes data = 1;  }
  | 
 
也就是说data数据是bytes类型,这意味着我们通过Gin从前端获取的视频要转化为字节数组,这样才能传给相应的微服务,然后对应的微服务实现视频上传。
下面是Gin的处理逻辑:
videoPb.PublishRequest和videoPb.PublishResponse就是你用proto文件生成对应的后缀为pb.go里面的东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   | func PublishHandler(ctx *gin.Context) { 	var req videoPb.PublishRequest 	 	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())) 	} 	 	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 作为参数传递给该函数。 
 
- 处理微服务的响应:
- 将微服务的响应信息提取出来,包括状态码和状态消息。
 
- 使用这些信息构建一个JSON响应,并返回给前端。
 
 
微服务处理
下面是对应的微服务处理逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
   | 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))      	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 函数将视频数据上传到云存储服务中(这里使用七牛云存储)。 
 
- 生成上传凭证和URL:
- 准备上传的参数,如存储空间、文件名等。
 
- 创建上传凭证,使用七牛云的 AccessKey 和 SecretKey。
 
- 通过七牛云的 SDK 进行文件上传,将视频数据上传到指定位置。
 
- 生成上传后的视频URL,结合存储域名和文件名。
 
 
- 设置微服务的响应:
- 根据上传成功与否,设置相应的状态码和状态消息。
 
- 将这些信息填充到 
videoPb.PublishResponse 实例中。 
 
- 辅助函数和UUID生成:
PublishResponseData 函数:用于填充响应对象的状态码和状态消息。 
GenerateUUID 函数:生成唯一标识符,通常用于生成上传文件的唯一键。