• 基于Go语言的网盘开发(GloudDisk)


    (记录一下自己做项目的过程) 基于go-zero实现的简易的网盘系统,如果有小伙伴对这个项目感兴趣,可以去网上搜索一些资料。这里推荐一下我学习的来源:【项目实战】基于Go-zero、Xorm的网盘系统_哔哩哔哩_bilibili 

    确定功能模块:

    目录

     xorm连接数据库并创建表结构

     集成go—zero

    一、用户模块

    (1)密码登录

    (2)邮箱注册

     (3)个人资料详情

    二、存储池模块

    (1)中心存储池资源管理

    ①文件上传

    (2)个人存储池资源管理 

    ①文件关联存储

    ②用户文件列表 

    ③用户文件名称修改

    ④用户文件夹创建

    ⑤用户文件删除

    ⑥用户文件移动

    三、文件共享模块

    (1)文件分享

    ①创建分享记录

    ②获取资源详情

    ③资源保存


     xorm连接数据库并创建表结构

     创建项目--安装xorm( go get xorm.io/xorm)

    文档地址:Xorm

    连接数据库:

    xorm.NewEngine("mysql", "root:123@/test?charset=utf8")

    先创建UserBasic结构体,为了之后的测试,如下:(新建models文件夹,在文件夹下新建user_basic.go)

    1. package Models
    2. type UserBasic struct {
    3. ID int
    4. Identity string
    5. Name string
    6. Password string
    7. Email string
    8. }
    9. func (table UserBasic) TableName() string {
    10. return "user_basic"
    11. }

    之后通过 engine.CreateTables(),参数为一个或多个空的对应Struct的指针,创建数据表,具体操作如下:(为了测试,新建一个文件夹test,新建xorm_test.go)

    1. package test
    2. import (
    3. "CloudDisk/Models"
    4. bytes2 "bytes"
    5. "encoding/json"
    6. _ "github.com/go-sql-driver/mysql"
    7. "testing"
    8. "xorm.io/xorm"
    9. )
    10. func TestXorm(t *testing.T) {
    11. engine, err := xorm.NewEngine("mysql", "root:123456@tcp(127.0.0.1:3306)/clouddisk?charset=utf8")
    12. if err!=nil {
    13. t.Fatal(err)
    14. }
    15. TableUser:=make([]*Models.UserBasic,0)
    16. m := new(Models.UserBasic)
    17. err = engine.CreateTables(m)
    18. if err!=nil {
    19. t.Fatal(err)
    20. }
    21. err = engine.Find(&TableUser)//这里查出来的是地址
    22. if err!=nil {
    23. t.Fatal(err)
    24. }
    25. //将以json格式输出
    26. bytes, err:= json.Marshal(TableUser)//转换成BYTE数组
    27. if err!=nil {
    28. t.Fatal(err)
    29. }
    30. dst := new(bytes2.Buffer)
    31. err = json.Indent(dst, bytes, "", " ") //转换为buffer
    32. if err!=nil {
    33. t.Fatal(err)
    34. }
    35. println(dst.String())
    36. }

     集成go—zero

    文档地址:简介 · go-zero document

     安装:

    go get -u github.com/zeromicro/go-zero

    因为项目比较小,所以直接选择单体服务就可以了,

    安装Goctl,完成后执行 goctl -v,如果输出版本信息则代表安装成功

    1. # Go 1.15 及之前版本
    2. go get -u github.com/zeromicro/go-zero/tools/goctl@latest
    3. # Go 1.16 及以后版本
    4. go install github.com/zeromicro/go-zero/tools/goctl@latest

    创建greet服务,如下图,因为我们 mkdircd 都已经完成了,所以直接  goctl api new [可自定义名字] (我的是goctl api new code,因为下面我会直接说code文件,所以希望大家不要迷糊我这code是啥了)

     之后启动服务:

    1. $ cd greet
    2. $ go run greet.go -f etc/greet-api.yaml

    之后通过http://localhost:8888/from/you来访问服务,如下图:

     可以看到当前的返回值为null,那是因为我们在 logic 文件里的 .go文件 没有写任何的业务逻辑(我的名字是code,所以这里是codelogic.go),如下图:

    如果我们改成 

    重新启动服务,会出现这样的页面:

     

    但是为什么返回的是Message呢?因为返回的response里面定义的是一个Message集。在code.api中可以看到,如下图: 

     以后我们就可以在这里写业务逻辑了。

    接下来我们来整合一下,将models文件放入code目录下,并在models中创建init.go用来连接数据库。如下:

     代码:

    1. package Models
    2. import (
    3. "log"
    4. "xorm.io/xorm"
    5. _ "github.com/go-sql-driver/mysql"
    6. )
    7. var Engine=Init()
    8. func Init() *xorm.Engine {
    9. engine, err := xorm.NewEngine("mysql", "root:123456@tcp(127.0.0.1:3306)/clouddisk?charset=utf8")
    10. if err!=nil {
    11. log.Println("engine Error:",err)//log包的println会自动return
    12. }
    13. return engine
    14. }

    然后在 codelogic.go 进行业务逻辑的实现: (其实就是将文件 xorm_test.go 中的代码复制过来进行测试)

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. bytes2 "bytes"
    5. "context"
    6. "encoding/json"
    7. "log"
    8. "CloudDisk/code/internal/svc"
    9. "CloudDisk/code/internal/types"
    10. "github.com/zeromicro/go-zero/core/logx"
    11. )
    12. type CodeLogic struct {
    13. logx.Logger
    14. ctx context.Context
    15. svcCtx *svc.ServiceContext
    16. }
    17. func NewCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CodeLogic {
    18. return &CodeLogic{
    19. Logger: logx.WithContext(ctx),
    20. ctx: ctx,
    21. svcCtx: svcCtx,
    22. }
    23. }
    24. func (l *CodeLogic) Code(req *types.Request) (resp *types.Response, err error) {
    25. TableUser:=make([]*Models.UserBasic,0)
    26. err = Models.Engine.Find(&TableUser)//这里查出来的是地址
    27. if err!=nil {
    28. log.Println("Find Error:",err)
    29. }
    30. //将以json格式输出
    31. bytes, err:= json.Marshal(TableUser)//转换成BYTE数组
    32. if err!=nil {
    33. log.Println("json Error:",err)
    34. }
    35. dst := new(bytes2.Buffer)
    36. err = json.Indent(dst, bytes, "", " ") //转换为buffer
    37. if err!=nil {
    38. log.Println("Indent Error:",err)
    39. }
    40. println(dst.String())
    41. resp=new(types.Response)
    42. resp.Message=dst.String()
    43. return
    44. }

    一、用户模块

    (1)密码登录

    在 code.api 中写登录handler的相关配置

    1. service code-api {
    2. @handler User//这个handler指的是生成在handler与logic下的文件所处理的句柄
    3. get /user/login (LoginRequest) returns (LoginReply)
    4. }
    5. type LoginRequest {
    6. Name string `form:"name"`
    7. Password string `json:"password"`
    8. }
    9. type LoginReply {
    10. Token string `json:"token"`
    11. }

     更新api,之后在 handler 与 logic 文件下都会出现新的.go文件

    goctl api go  -api code.api -dir . -style go_zero

     在用户成功登陆之后,那么存到数据库的密码,我们也需要加密一下,这里用到的是MD5。

    两个方法:

    (1)md5.New() 初始化一个MD5对象,返回的是hash.Hash对象。

             函数原型: func New() hash.Hash

             该对象实现了hash.Hash的Sum接口。

    (2)md5.Sum() 计算出MD5校验和。

             函数原型:func Sum(data []byte) [Size]byte
             他并不是对data进行校验计算,而是对hash.Hash对象内部存储的内容进行校验和计算然后将其追加到data的后面形成一个新的byte切片。该方法返回一个Size大小为16的byte数组,对于MD5来说就是一个128bit的16字节byte数组。

    新建文件 helper,创建 helper.go 写入MD5函数 

    1. package helper
    2. import (
    3. "crypto/md5"
    4. "fmt"
    5. )
    6. func Md5(s string) string {
    7. return fmt.Sprintf("%x",md5.Sum([]byte(s)))
    8. }

    我们需要生成 token,而 token 需要用到 jwt 进行加密。这里介绍一下 jwt-go 库

    使用 jwt-go 库生成 token,我们需要定义需求(claims),也就是说我们需要通过 jwt 传输的数据。假如我们需要传输 ID 和 Username,我们可以定义 Claims 结构体,其中包含 ID 和 Username 字段,还有在 jwt-go 包预定义的 jwt.StandardClaims。

    使用 jwt-go 库根据指定的算法生成 jwt token ,主要用到两个方法:

    (1)jwt.NewWithClaims 方法:

    func jwt.NewWithClaims(method jwt.SigningMethod, claims jwt.Claims) *jwt.Token

    jwt.NewWithClaims 方法根据 Claims 结构体创建 Token 示例。

    参数 1 是 jwt.SigningMethod,最常用的是 jwt.SigningMethodHS256 这种 crypto.Hash 加密算法的方案。

    参数 2 是 Claims,也就是我们自己定义的UserClaim,UserClaim嵌入在自定义类型中,以方便对标准声明进行编码,解析和验证。

    (2)SignedString 方法:

    func (*jwt.Token).SignedString(key interface{}) (string, error)

    SignedString 方法根据传入的空接口类型参数 key,返回完整的签名令牌。

    解析 token

    使用 jwt-go 库解析 token

    (1)jwt.ParseWithClaims 方法:

    func jwt.ParseWithClaims(tokenString string, claims jwt.Claims, keyFunc jwt.Keyfunc) (*jwt.Token, error)

    jwt.ParseWithClaims 方法用于解析鉴权的声明,返回 *jwt.Token。

    创建文件夹define,用来定义token需要用到的claims

    1. package define
    2. import "github.com/dgrijalva/jwt-go"
    3. type UserClaim struct {
    4. Id int
    5. Identity string
    6. Name string
    7. jwt.StandardClaims
    8. }
    9. var JwtKey="cloud-disk-key"

    接下来定义生成token的方法,写在helper文件里

    1. func GenerateToken(id int,name,identity string) (string,error) {
    2. uc:=define.UserClaim{
    3. Id:id,
    4. Identity: identity,
    5. Name: name,
    6. }
    7. token := jwt.NewWithClaims(jwt.SigningMethodHS256, uc) //生成token
    8. //给token进行加密
    9. tokenString, err := token.SignedString([]byte(define.JwtKey))
    10. if err!=nil {
    11. return "", err
    12. }
    13. return tokenString,nil
    14. }

     准备工作都做好了,接下来我们来写user-login业务逻辑,user_logic.go 代码如下:

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "context"
    6. "errors"
    7. "CloudDisk/code/internal/svc"
    8. "CloudDisk/code/internal/types"
    9. "github.com/zeromicro/go-zero/core/logx"
    10. )
    11. type UserLogic struct {
    12. logx.Logger
    13. ctx context.Context
    14. svcCtx *svc.ServiceContext
    15. }
    16. func NewUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserLogic {
    17. return &UserLogic{
    18. Logger: logx.WithContext(ctx),
    19. ctx: ctx,
    20. svcCtx: svcCtx,
    21. }
    22. }
    23. func (l *UserLogic) User(req *types.LoginRequest) (resp *types.LoginReply, err error) {
    24. // todo: add your logic here and delete this line
    25. user := new(Models.UserBasic)
    26. //1.从数据库中查询当前用户
    27. get, err := Models.Engine.Where("name= ? AND password= ?", req.Name, helper.Md5(req.Password)).Get(user)
    28. if err!=nil {
    29. return nil, err
    30. }
    31. if !get {
    32. return nil,errors.New("用户名或密码错误")
    33. }
    34. //2.生成token
    35. token, err := helper.GenerateToken(user.ID, user.Name, user.Identity)
    36. if err!=nil {
    37. return nil,err
    38. }
    39. resp=new(types.LoginReply)
    40. resp.Token=token
    41. return
    42. }

    之后我们进行重新编译(下面两句话会频繁的用到,每次写完code.api都要goctl一下)

    goctl api go -api code.api -dir . -style go_zero

     然后运行

    go run code.go -f etc/code-api.yaml

    使用postman软件,帮助测试 (这里在code.api中我将输入json改为了form形式)

    (2)邮箱注册

    go get github.com/jordan-wright/email

     安装email,源址https://github.com/jordan-wright/email

    go get github.com/go-redis/redis/v8

     安装redis,源址GitHub - go-redis/redis: Type-safe Redis client for Golang

    $ go get github.com/satori/go.uuid

     安装uuid ,源址GitHub - satori/go.uuid: UUID package for Go

    在 init.go 中加入 redis 的配置

    1. package Models
    2. import (
    3. "context"
    4. "github.com/go-redis/redis/v8"
    5. _ "github.com/go-sql-driver/mysql"
    6. "log"
    7. "xorm.io/xorm"
    8. )
    9. var Engine=Init()
    10. var ctx = context.Background()
    11. var Redis = InitRedis()
    12. func Init() *xorm.Engine {
    13. engine, err := xorm.NewEngine("mysql", "root:123456@tcp(127.0.0.1:3306)/clouddisk?charset=utf8")
    14. if err!=nil {
    15. log.Println("engine Error:",err)//log包的println会自动return
    16. }
    17. return engine
    18. }
    19. func InitRedis() *redis.Client {
    20. return redis.NewClient(&redis.Options{
    21. Addr: "127.0.0.1:6379",
    22. Password: "", // no password set
    23. DB: 0, // use default DB
    24. })
    25. }

     在 helper 中定义随机数生成,为了生成随机的验证码;以及 uuid ,为了生成 identity

    1. package helper
    2. import (
    3. "CloudDisk/code/define"
    4. "crypto/md5"
    5. "fmt"
    6. "github.com/dgrijalva/jwt-go"
    7. "github.com/jordan-wright/email"
    8. uuid "github.com/satori/go.uuid"
    9. "math/rand"
    10. "net/smtp"
    11. "time"
    12. )
    13. func Md5(s string) string {
    14. return fmt.Sprintf("%x",md5.Sum([]byte(s)))
    15. }
    16. func GenerateToken(id int,name,identity string) (string,error) {
    17. uc:=define.UserClaim{
    18. Id:id,
    19. Identity: identity,
    20. Name: name,
    21. }
    22. token := jwt.NewWithClaims(jwt.SigningMethodHS256, uc) //生成token
    23. //给token进行加密
    24. tokenString, err := token.SignedString([]byte(define.JwtKey))
    25. if err!=nil {
    26. return "", err
    27. }
    28. return tokenString,nil
    29. }
    30. func MailSendCode(mail,code string) error {
    31. e := email.NewEmail()
    32. e.From = ""//发送者姓名,发送者邮箱地址
    33. e.To = []string{mail}//接收着
    34. e.Subject = "验证码测试"//发送的主题
    35. e.HTML = []byte("

      "+code+"

      "
      )
    36. err := e.Send("smtp.qq.com:25", smtp.PlainAuth("", "@qq.com", "jjj", "smtp.qq.com"), )
    37. if err!=nil {
    38. return err
    39. }
    40. return nil
    41. }
    42. func RandCode() string {
    43. s:="1234567890"
    44. rand.Seed(time.Now().UnixNano())
    45. code:=""
    46. for i := 0; i < 6; i++ {
    47. code+=string(s[rand.Intn(len(s))])
    48. }
    49. return code
    50. }
    51. func GetUUID() string {
    52. return uuid.NewV4().String()
    53. }

     发送验证码的业务逻辑

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "CloudDisk/code/internal/svc"
    6. "CloudDisk/code/internal/types"
    7. "context"
    8. "errors"
    9. "time"
    10. "github.com/zeromicro/go-zero/core/logx"
    11. )
    12. type MailCodeSendLogic struct {
    13. logx.Logger
    14. ctx context.Context
    15. svcCtx *svc.ServiceContext
    16. }
    17. func NewMailCodeSendLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MailCodeSendLogic {
    18. return &MailCodeSendLogic{
    19. Logger: logx.WithContext(ctx),
    20. ctx: ctx,
    21. svcCtx: svcCtx,
    22. }
    23. }
    24. func (l *MailCodeSendLogic) MailCodeSend(req *types.MailCodeSendRequest) (resp *types.MailCodeSendReply, err error) {
    25. // todo: add your logic here and delete this line
    26. //该邮箱未被注册
    27. count, err := Models.Engine.Where("email= ?", req.Email).Count(new(Models.UserBasic))
    28. if err!=nil {
    29. return
    30. }
    31. if count>0 {
    32. err=errors.New("该邮箱已经被注册过了")
    33. return
    34. }
    35. //获取验证码
    36. code:=helper.RandCode()
    37. //存储验证码
    38. Models.Redis.Set(l.ctx, req.Email,code,time.Second * 300)
    39. //发送验证码
    40. err = helper.MailSendCode(req.Email, code)
    41. if err!=nil {
    42. return nil, err
    43. }
    44. return
    45. }

    用户注册的业务逻辑

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "CloudDisk/code/internal/svc"
    6. "CloudDisk/code/internal/types"
    7. "context"
    8. "errors"
    9. "github.com/zeromicro/go-zero/core/logx"
    10. "log"
    11. )
    12. type UserRegisterLogic struct {
    13. logx.Logger
    14. ctx context.Context
    15. svcCtx *svc.ServiceContext
    16. }
    17. func NewUserRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserRegisterLogic {
    18. return &UserRegisterLogic{
    19. Logger: logx.WithContext(ctx),
    20. ctx: ctx,
    21. svcCtx: svcCtx,
    22. }
    23. }
    24. func (l *UserRegisterLogic) UserRegister(req *types.UserRegisterRequest) (resp *types.UserRegisterReply, err error) {
    25. //判断code是否一致
    26. result, err := Models.Redis.Get(l.ctx, req.Email).Result()
    27. if err!=nil {
    28. return nil, errors.New("未获取该邮箱的验证码")
    29. }
    30. if result!=req.Code {
    31. err=errors.New("验证码错误")
    32. return
    33. }
    34. //判断用户名是否已经存在
    35. count, err := Models.Engine.Where("name= ?", req.Name).Count(new(Models.UserBasic))
    36. if err!=nil {
    37. return nil, err
    38. }
    39. if count>0 {
    40. err=errors.New("用户名已经存在")
    41. return
    42. }
    43. //数据入库,开始注册信息
    44. user:=&Models.UserBasic{
    45. Name: req.Name,
    46. Identity:helper.GetUUID(),
    47. Email: req.Email,
    48. Password: helper.Md5(req.Password),
    49. }
    50. insert, err := Models.Engine.Insert(user)
    51. if err!=nil {
    52. return nil, err
    53. }
    54. log.Println("insert user row:",insert)
    55. return
    56. }

     (3)个人资料详情

     通过 identity 来获取用户信息

    code.api新增:

    1. service code-api {
    2. //用户登录
    3. @handler UserLogin//这个handler指的是生成在handler与logic下的文件所处理的句柄
    4. post /user/login (LoginRequest) returns (LoginReply)
    5. //用户详情
    6. @handler UserDetail
    7. post /user/detail (DetailRequest) returns (DetailReply)
    8. }
    9. type LoginRequest {
    10. Name string `form:"name"`
    11. Password string `form:"password"`
    12. }
    13. type LoginReply {
    14. Token string `json:"token"`
    15. }
    16. type DetailRequest {
    17. Identity string `json:"identity"`
    18. }
    19. type DetailReply {
    20. Name string `json:"name"`
    21. Email string `json:"email"`
    22. }

     之后 goctl api go -api code.api -dir . -style go_zero 生成编译,编写detail业务逻辑

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "context"
    5. "errors"
    6. "CloudDisk/code/internal/svc"
    7. "CloudDisk/code/internal/types"
    8. "github.com/zeromicro/go-zero/core/logx"
    9. )
    10. type UserDetailLogic struct {
    11. logx.Logger
    12. ctx context.Context
    13. svcCtx *svc.ServiceContext
    14. }
    15. func NewUserDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserDetailLogic {
    16. return &UserDetailLogic{
    17. Logger: logx.WithContext(ctx),
    18. ctx: ctx,
    19. svcCtx: svcCtx,
    20. }
    21. }
    22. func (l *UserDetailLogic) UserDetail(req *types.DetailRequest) (resp *types.DetailReply, err error) {
    23. // todo: add your logic here and delete this line
    24. resp=&types.DetailReply{}
    25. m := new(Models.UserBasic)
    26. get, err := Models.Engine.Where("identity= ? ", req.Identity).Get(m)
    27. if err!=nil {
    28. return nil, err
    29. }
    30. if !get {
    31. return nil, errors.New("该用户不存在")
    32. }
    33. resp.Name=m.Name
    34. resp.Email=m.Email
    35. return
    36. }

    二、存储池模块

    我们先修改一下数据库配置路由,在etc文件的 code_api.yaml 中加入如下:

    1. Name: code-api
    2. Host: 0.0.0.0
    3. Port: 8888
    4. Mysql:
    5. DataSource: root:123456@tcp(127.0.0.1:3306)/clouddisk?charset=utf8
    6. Redis:
    7. Addr: 127.0.0.1:6379

    在config文件中加入:

    1. package config
    2. import "github.com/zeromicro/go-zero/rest"
    3. type Config struct {
    4. rest.RestConf
    5. Mysql struct{
    6. DataSource string
    7. }
    8. Redis struct{
    9. Addr string
    10. }
    11. }

    同样在 service_context.go 中也要加入:

    1. package svc
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/internal/config"
    5. "CloudDisk/code/internal/middleware"
    6. "github.com/go-redis/redis/v8"
    7. "github.com/zeromicro/go-zero/rest"
    8. "xorm.io/xorm"
    9. )
    10. type ServiceContext struct {
    11. Config config.Config
    12. Engine *xorm.Engine
    13. RDB *redis.Client
    14. Auth rest.Middleware
    15. }
    16. func NewServiceContext(c config.Config) *ServiceContext {
    17. return &ServiceContext{
    18. Config: c,
    19. Engine:Models.Init(c.Mysql.DataSource),
    20. RDB:Models.InitRedis(c),
    21. Auth: middleware.NewAuthMiddleware().Handle,
    22. }
    23. }

    当然,在做以下业务逻辑的时候,首先需要加一个中间件,用来验证用户是否已经登录,如果不登录是无法使用以下功能的。在go-zero中,中间件可以分为路由中间件和全局中间件,路由中间件是指某一些特定路由需要实现中间件逻辑,而全局中间件的服务范围则是整个服务。我们这里使用的是路由中间件 。对于中间件,需要添加 Middleware 声明。

    所以我们需要再写一对 service code-api{},在这之上需要 Middleware 声明。例如文件上传的code.api配置,然后 goctl api go -api code.api -dir . -style go_zero 一下会自动生成Middleware的文件,在文件中配置如下

    1. package middleware
    2. import (
    3. "CloudDisk/code/helper"
    4. "net/http"
    5. )
    6. type AuthMiddleware struct {
    7. }
    8. func NewAuthMiddleware() *AuthMiddleware {
    9. return &AuthMiddleware{}
    10. }
    11. func (m *AuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
    12. return func(w http.ResponseWriter, r *http.Request) {
    13. // TODO generate middleware implement function, delete after code implementation
    14. auth:=r.Header.Get("Authorization")
    15. if auth =="" {
    16. w.WriteHeader(http.StatusUnauthorized)
    17. w.Write([]byte("Unauthorized"))
    18. return
    19. }
    20. uc, err := helper.AnalyzeToken(auth)
    21. if err!=nil {
    22. w.WriteHeader(http.StatusUnauthorized)
    23. w.Write([]byte(err.Error()))
    24. return
    25. }
    26. r.Header.Set("UserId",string(rune(uc.Id)))
    27. r.Header.Set("UserIdentity",uc.Identity)
    28. r.Header.Set("UserName",uc.Name)
    29. // Passthrough to next handler if need
    30. next(w, r)
    31. }
    32. }

    这里用到了token的解析,具体如下:

    1. //AnalyzeToken Token解析
    2. func AnalyzeToken(token string) (*define.UserClaim, error) {
    3. uc:=new(define.UserClaim)
    4. claims, err := jwt.ParseWithClaims(token, uc, func(token *jwt.Token) (interface{}, error) {
    5. return []byte(define.JwtKey), nil
    6. })
    7. if err != nil {
    8. return nil,err
    9. }
    10. if !claims .Valid{
    11. return uc,errors.New("token is invalid")
    12. }
    13. return uc,err
    14. }

      当然同样也要在 service_context.go 中也要加入Middleware 的声明。(代码跟上面一样,不在复制!)

    (1)中心存储池资源管理

    ①文件上传

    在Models里加入 RepositoryPool

    1. package Models
    2. import "time"
    3. type RepositoryPool struct {
    4. Id int
    5. Identity string
    6. Hash string
    7. Name string
    8. Ext string
    9. Size int64
    10. Path string
    11. createdAt time.Time `xorm:"created"`
    12. UpdatedAt time.Time `xorm:"updated"`
    13. DeletedAt time.Time `xorm:"deleted"`
    14. }
    15. func (table RepositoryPool) TableName() string {
    16. return "repository_pool"
    17. }

     在code.api代码中,添加如下代码:

    1. @server(
    2. middleware : Auth
    3. )
    4. service code-api {
    5. //文件上传
    6. @handler FileUpload
    7. post /file/upload (FileUploadRequest) returns (FileUploadReply)
    8. }
    9. type FileUploadRequest {
    10. Hash string `json:"hash,optional"`
    11. Name string `json:"name,optional"`
    12. Ext string `json:"ext,optional"`
    13. Size int `json:"size,optional"`
    14. Path string `json:"path,optional"`
    15. }
    16. type FileUploadReply {
    17. Identity string `json:"identity"`
    18. Ext string `json:"ext"`
    19. Name string `json:"name"`
    20. }

     在文件上传这里我们采用 CosUpload 文件上传到腾讯云,帮助文档在这里---------------------------------------------------------------》》》》》对象存储 快速入门-SDK 文档-文档中心-腾讯云

    在 helper 文件中加入 CosUpload 文件上传的业务逻辑

    1. //CosUpload 文件上传到腾讯云
    2. func CosUpload(r *http.Request) (string,error) {
    3. u, _ := url.Parse(define.CosBucket)
    4. b := &cos.BaseURL{BucketURL: u}
    5. c := cos.NewClient(b, &http.Client{
    6. Transport: &cos.AuthorizationTransport{
    7. //如实填写账号和密钥,也可以设置为环境变量
    8. SecretID: define.TencentSecretID,
    9. SecretKey: define.TencentSecretKey,
    10. },
    11. })
    12. file, fileHeader, err := r.FormFile("file")
    13. name := "cloud-disk/"+GetUUID()+path.Ext(fileHeader.Filename)
    14. _, err = c.Object.Put(context.Background(), name, file,nil)
    15. if err != nil {
    16. panic(err)
    17. }
    18. return define.CosBucket+"/"+name,nil
    19. }

    file_upload_handler.go 中写入如下代码:这次我们是先判断一下文件是否上传过,之后将信息写给 logic 中的 req 。

    1. package handler
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "crypto/md5"
    6. "fmt"
    7. "net/http"
    8. "path"
    9. "CloudDisk/code/internal/logic"
    10. "CloudDisk/code/internal/svc"
    11. "CloudDisk/code/internal/types"
    12. "github.com/zeromicro/go-zero/rest/httpx"
    13. )
    14. func FileUploadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
    15. return func(w http.ResponseWriter, r *http.Request) {
    16. var req types.FileUploadRequest
    17. if err := httpx.Parse(r, &req); err != nil {
    18. httpx.Error(w, err)
    19. return
    20. }
    21. file, fileHeader, err2 := r.FormFile("file")
    22. if err2!=nil {
    23. return
    24. }
    25. //判断文件是否存在
    26. bytes := make([]byte, fileHeader.Size)
    27. _, err2 = file.Read(bytes)
    28. if err2!=nil {
    29. return
    30. }
    31. hash:=fmt.Sprintf("%x",md5.Sum(bytes))
    32. rp:=new(Models.RepositoryPool)
    33. get, err2 := svcCtx.Engine.Where("hash=?", hash).Get(rp)
    34. if err2!=nil {
    35. return
    36. }
    37. if get {
    38. httpx.OkJson(w,&types.FileUploadReply{Identity: rp.Identity, Ext: rp.Ext, Name: rp.Name})
    39. return
    40. }
    41. //往cos中存储文件
    42. cosPath, err2 := helper.CosUpload(r)
    43. if err2!=nil {
    44. return
    45. }
    46. //往 logic 中传递req
    47. req.Name=fileHeader.Filename
    48. req.Ext=path.Ext(fileHeader.Filename)
    49. req.Size= int(fileHeader.Size)
    50. req.Hash=hash
    51. req.Path=cosPath
    52. l := logic.NewFileUploadLogic(r.Context(), svcCtx)
    53. resp, err := l.FileUpload(&req)
    54. if err != nil {
    55. httpx.Error(w, err)
    56. } else {
    57. httpx.OkJson(w, resp)
    58. }
    59. }
    60. }

    file_upload_logic.go 业务逻辑代码如下:

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "context"
    6. "fmt"
    7. "CloudDisk/code/internal/svc"
    8. "CloudDisk/code/internal/types"
    9. "github.com/zeromicro/go-zero/core/logx"
    10. )
    11. type FileUploadLogic struct {
    12. logx.Logger
    13. ctx context.Context
    14. svcCtx *svc.ServiceContext
    15. }
    16. func NewFileUploadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *FileUploadLogic {
    17. return &FileUploadLogic{
    18. Logger: logx.WithContext(ctx),
    19. ctx: ctx,
    20. svcCtx: svcCtx,
    21. }
    22. }
    23. func (l *FileUploadLogic) FileUpload(req *types.FileUploadRequest) (resp *types.FileUploadReply, err error) {
    24. // todo: add your logic here and delete this line
    25. rp := &Models.RepositoryPool{
    26. Identity: helper.GetUUID(),
    27. Hash: req.Hash,
    28. Name: req.Name,
    29. Ext: req.Ext,
    30. Size: int64(req.Size),
    31. Path: req.Path,
    32. }
    33. _, err = l.svcCtx.Engine.Insert(rp)
    34. if err!=nil {
    35. return nil, err
    36. }
    37. resp=new(types.FileUploadReply)
    38. resp.Identity=rp.Identity
    39. resp.Ext=rp.Ext
    40. resp.Name=rp.Name
    41. fmt.Println(resp.Identity)
    42. return
    43. }

    (2)个人存储池资源管理 

    ①文件关联存储

    code.api

    1. //用户文件的关联存储
    2. @handler UserRepositorySave
    3. post /user/repository/save (UserRepositorySaveRequest) returns (UserRepositorySaveReply)
    4. type UserRepositorySaveRequest {
    5. ParentId int64 `json:"parentId"`
    6. RepositoryIdentity string `json:"repositoryIdentity"`
    7. Ext string `json:"ext"`
    8. Name string `json:"name"`
    9. }
    10. type UserRepositorySaveReply {
    11. }

     Models新增

    1. package Models
    2. import "time"
    3. type UserRepository struct {
    4. Id int
    5. Identity string
    6. UserIdentity string
    7. ParentId int64
    8. RepositoryIdentity string
    9. Ext string
    10. Name string
    11. CreatedAt time.Time `xorm:"created"`
    12. UpdatedAt time.Time `xorm:"updated"`
    13. DeletedAt time.Time `xorm:"deleted"`
    14. }
    15. func (table UserRepository) TableName() string {
    16. return "user_repository"
    17. }

     在 user_repository_save_handler.go 修改一下 UserRepositorySave 函数的参数,将UserIdentity 传入,代码如下:

    1. package handler
    2. import (
    3. "net/http"
    4. "CloudDisk/code/internal/logic"
    5. "CloudDisk/code/internal/svc"
    6. "CloudDisk/code/internal/types"
    7. "github.com/zeromicro/go-zero/rest/httpx"
    8. )
    9. func UserRepositorySaveHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
    10. return func(w http.ResponseWriter, r *http.Request) {
    11. var req types.UserRepositorySaveRequest
    12. if err := httpx.Parse(r, &req); err != nil {
    13. httpx.Error(w, err)
    14. return
    15. }
    16. l := logic.NewUserRepositorySaveLogic(r.Context(), svcCtx)
    17. resp, err := l.UserRepositorySave(&req,r.Header.Get("UserIdentity"))
    18. if err != nil {
    19. httpx.Error(w, err)
    20. } else {
    21. httpx.OkJson(w, resp)
    22. }
    23. }
    24. }

     接下来的每一个业务逻辑块都需要在 handler 里加入,之后我就不再详细说明了。

    logic业务逻辑:(非常简单,就是个插入) 

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "context"
    6. "CloudDisk/code/internal/svc"
    7. "CloudDisk/code/internal/types"
    8. "github.com/zeromicro/go-zero/core/logx"
    9. )
    10. type UserRepositorySaveLogic struct {
    11. logx.Logger
    12. ctx context.Context
    13. svcCtx *svc.ServiceContext
    14. }
    15. func NewUserRepositorySaveLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserRepositorySaveLogic {
    16. return &UserRepositorySaveLogic{
    17. Logger: logx.WithContext(ctx),
    18. ctx: ctx,
    19. svcCtx: svcCtx,
    20. }
    21. }
    22. func (l *UserRepositorySaveLogic) UserRepositorySave(req *types.UserRepositorySaveRequest, userIdentity string) (resp *types.UserRepositorySaveReply, err error) {
    23. // todo: add your logic here and delete this line
    24. ur := &Models.UserRepository{
    25. Identity: helper.GetUUID(),
    26. UserIdentity: userIdentity,
    27. ParentId: req.ParentId,
    28. RepositoryIdentity: req.RepositoryIdentity,
    29. Ext: req.Ext,
    30. Name: req.Name,
    31. }
    32. _, err = l.svcCtx.Engine.Insert(ur)
    33. if err!=nil {
    34. return
    35. }
    36. return
    37. }

    ②用户文件列表 

    code.api 

    1. //用户文件列表
    2. @handler UserFileList
    3. get /user/file/list (UserFileListReguest) returns (UserFileListReply)
    4. type UserFileListReguest {
    5. Id int64 `json:"id,optional"`
    6. Page int `json:"page,optional"`
    7. Size int `json:"size,optional"`
    8. }
    9. type UserFileListReply {
    10. List []*UserFile `json:"list"`
    11. Count int `json:"count"`
    12. }

    logic 业务逻辑做到了分页的多表 join 查询 

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/define"
    5. "context"
    6. "time"
    7. "CloudDisk/code/internal/svc"
    8. "CloudDisk/code/internal/types"
    9. "github.com/zeromicro/go-zero/core/logx"
    10. )
    11. type UserFileListLogic struct {
    12. logx.Logger
    13. ctx context.Context
    14. svcCtx *svc.ServiceContext
    15. }
    16. func NewUserFileListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserFileListLogic {
    17. return &UserFileListLogic{
    18. Logger: logx.WithContext(ctx),
    19. ctx: ctx,
    20. svcCtx: svcCtx,
    21. }
    22. }
    23. func (l *UserFileListLogic) UserFileList(req *types.UserFileListReguest,userIdentity string) (resp *types.UserFileListReply, err error) {
    24. // todo: add your logic here and delete this line
    25. uf := make( []*types.UserFile,0)
    26. //var cnt int64
    27. resp = new(types.UserFileListReply)
    28. size:=req.Size
    29. if size==0 {
    30. size=define.PageSize
    31. }
    32. page:=req.Page
    33. if page ==0{
    34. page=1
    35. }
    36. offset:=(page-1)*size
    37. //查询用户文件列表
    38. l.svcCtx.Engine.ShowSQL(true)//这样就可以看到运行时的sql语句
    39. err = l.svcCtx.Engine.Table("user_repository"). Where("parent_id = ? AND user_identity = ? ",req.Id,userIdentity).
    40. Select("user_repository.id,user_repository.identity,user_repository.repository_identity,user_repository.ext,"+
    41. "user_repository.name,repository_pool.path,repository_pool.size").
    42. Join("LEFT","repository_pool","user_repository.repository_identity=repository_pool.identity").
    43. Where("user_repository.deleted_at=? OR user_repository.deleted_at IS NULL",time.Time{}.Format("2006-01-02 15:04:05")).
    44. Limit(size,offset).Find(&uf)
    45. if err != nil {
    46. return
    47. }
    48. count, err := l.svcCtx.Engine.Where("parent_id = ? AND user_identity = ? ", req.Id, userIdentity).Count(new(Models.UserRepository))
    49. if err!=nil {
    50. return
    51. }
    52. resp.List = uf
    53. resp.Count = int(count)
    54. return
    55. }

    ③用户文件名称修改

    code.api

    1. //用户文件名称修改
    2. @handler UserFileNameUpdate
    3. post /user/file/name/update (UserFileNameUpdateReguest) returns (UserFileNameUpdateReply)
    4. type UserFileNameUpdateReguest {
    5. Identity string `json:"identity"`
    6. Name string `json:"name"`
    7. }
    8. type UserFileNameUpdateReply {
    9. }

     logic 业务实现

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "context"
    5. "errors"
    6. "CloudDisk/code/internal/svc"
    7. "CloudDisk/code/internal/types"
    8. "github.com/zeromicro/go-zero/core/logx"
    9. )
    10. type UserFileNameUpdateLogic struct {
    11. logx.Logger
    12. ctx context.Context
    13. svcCtx *svc.ServiceContext
    14. }
    15. func NewUserFileNameUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserFileNameUpdateLogic {
    16. return &UserFileNameUpdateLogic{
    17. Logger: logx.WithContext(ctx),
    18. ctx: ctx,
    19. svcCtx: svcCtx,
    20. }
    21. }
    22. func (l *UserFileNameUpdateLogic) UserFileNameUpdate(req *types.UserFileNameUpdateReguest,userIdentity string) (resp *types.UserFileNameUpdateReply, err error) {
    23. // todo: add your logic here and delete this line
    24. //判断当前名称在该层下面是否存在
    25. count, err := l.svcCtx.Engine.Where("name=? AND parent_id=(SELECT parent_id FROM user_repository ur WHERE ur.identity=?)", req.Name, req.Identity).Count(new(Models.UserRepository))
    26. if err!=nil {
    27. return nil, err
    28. }
    29. if count >0{
    30. return nil,errors.New("该名称已经存在")
    31. }
    32. //文件修改
    33. data := &Models.UserRepository{Name: req.Name}
    34. l.svcCtx.Engine.Where("identity = ? AND user_identity = ? ", req.Identity, userIdentity).Update(data)
    35. if err != nil {
    36. return
    37. }
    38. return
    39. }

    ④用户文件夹创建

    code.api

    1. //用户文件夹创建
    2. @handler UserFolderCreate
    3. post /user/folder/create (UserFolderCreateReguest) returns (UserFolderCreateReply)
    4. type UserFolderCreateReguest {
    5. Name string `json:"name"`
    6. ParentId int64 `json:"parent_id"`
    7. }
    8. type UserFolderCreateReply {
    9. Identity string `json:"identity"`
    10. }

     logic

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "context"
    6. "errors"
    7. "CloudDisk/code/internal/svc"
    8. "CloudDisk/code/internal/types"
    9. "github.com/zeromicro/go-zero/core/logx"
    10. )
    11. type UserFolderCreateLogic struct {
    12. logx.Logger
    13. ctx context.Context
    14. svcCtx *svc.ServiceContext
    15. }
    16. func NewUserFolderCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserFolderCreateLogic {
    17. return &UserFolderCreateLogic{
    18. Logger: logx.WithContext(ctx),
    19. ctx: ctx,
    20. svcCtx: svcCtx,
    21. }
    22. }
    23. func (l *UserFolderCreateLogic) UserFolderCreate(req *types.UserFolderCreateReguest,userIdentity string) (resp *types.UserFolderCreateReply, err error) {
    24. // todo: add your logic here and delete this line
    25. //判断当前名称在该层下面是否存在
    26. count, err := l.svcCtx.Engine.Where("name=? AND parent_id=?", req.Name, req.ParentId).Count(new(Models.UserRepository))
    27. if err!=nil {
    28. return nil, err
    29. }
    30. if count >0{
    31. return nil,errors.New("该名称已经存在")
    32. }
    33. //创建文件夹
    34. data:=&Models.UserRepository{
    35. Identity: helper.GetUUID(),
    36. UserIdentity: userIdentity,
    37. ParentId: req.ParentId,
    38. Name: req.Name,
    39. }
    40. _, err = l.svcCtx.Engine.Insert(data)
    41. if err != nil {
    42. return
    43. }
    44. return
    45. }

    ⑤用户文件删除

    code.api

    1. //用户文件删除
    2. @handler UserFileDelete
    3. post /user/file/delete (UserFileDeleteReguest) returns (UserFileDeleteReply)
    4. type UserFileDeleteReguest {
    5. Identity string `json:"identity"`
    6. }
    7. type UserFileDeleteReply {
    8. }

     logic

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "context"
    5. "CloudDisk/code/internal/svc"
    6. "CloudDisk/code/internal/types"
    7. "github.com/zeromicro/go-zero/core/logx"
    8. )
    9. type UserFileDeleteLogic struct {
    10. logx.Logger
    11. ctx context.Context
    12. svcCtx *svc.ServiceContext
    13. }
    14. func NewUserFileDeleteLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserFileDeleteLogic {
    15. return &UserFileDeleteLogic{
    16. Logger: logx.WithContext(ctx),
    17. ctx: ctx,
    18. svcCtx: svcCtx,
    19. }
    20. }
    21. func (l *UserFileDeleteLogic) UserFileDelete(req *types.UserFileDeleteReguest,userIdentity string) (resp *types.UserFileDeleteReply, err error) {
    22. // todo: add your logic here and delete this line
    23. _, err = l.svcCtx.Engine.Where("user_identity=? AND identity=?", userIdentity, req.Identity).Delete(new(Models.UserRepository))
    24. if err!=nil {
    25. return
    26. }
    27. return
    28. }

    ⑥用户文件移动

    code.api,注意是 PUT 请求

    1. //用户文件移动
    2. @handler UserFileMove
    3. put /user/file/move (UserFileMoveReguest) returns (UserFileMoveReply)
    4. type UserFileMoveReguest {
    5. Identity string `json:"identity"`
    6. ParentIdentity string `json:"parentIdentity"`
    7. }
    8. type UserFileMoveReply {
    9. }

     logic

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "context"
    5. "errors"
    6. "CloudDisk/code/internal/svc"
    7. "CloudDisk/code/internal/types"
    8. "github.com/zeromicro/go-zero/core/logx"
    9. )
    10. type UserFileMoveLogic struct {
    11. logx.Logger
    12. ctx context.Context
    13. svcCtx *svc.ServiceContext
    14. }
    15. func NewUserFileMoveLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserFileMoveLogic {
    16. return &UserFileMoveLogic{
    17. Logger: logx.WithContext(ctx),
    18. ctx: ctx,
    19. svcCtx: svcCtx,
    20. }
    21. }
    22. func (l *UserFileMoveLogic) UserFileMove(req *types.UserFileMoveReguest,userIdentity string) (resp *types.UserFileMoveReply, err error) {
    23. // todo: add your logic here and delete this line
    24. parentDate := new(Models.UserRepository)
    25. has, err := l.svcCtx.Engine.Where("identity=? AND user_identity=?", req.ParentIdentity, userIdentity).Get(parentDate)
    26. if err!=nil {
    27. return nil, err
    28. }
    29. if !has {
    30. return nil,errors.New("文件夹不存在!")
    31. }
    32. //更新记录的ParentID
    33. _, err = l.svcCtx.Engine.Where("identity=?", req.Identity).Update(Models.UserRepository{
    34. ParentId: int64(parentDate.Id),
    35. })
    36. return
    37. }

    三、文件共享模块

    (1)文件分享

    ①创建分享记录

    code.api

    1. //创建分享记录
    2. @handler ShareBasicCreate
    3. post /share/basic/create (ShareBasicCreateRequest) returns (ShareBasicCreateReply)
    4. type ShareBasicCreateRequest {
    5. RepositoryIdentity string `json:"repository_identity"`
    6. ExpiredTime int `json:"expired_time"`
    7. }
    8. type ShareBasicCreateReply {
    9. Identity string `json:"identity"`
    10. }

    logic

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "context"
    6. "CloudDisk/code/internal/svc"
    7. "CloudDisk/code/internal/types"
    8. "github.com/zeromicro/go-zero/core/logx"
    9. )
    10. type ShareBasicCreateLogic struct {
    11. logx.Logger
    12. ctx context.Context
    13. svcCtx *svc.ServiceContext
    14. }
    15. func NewShareBasicCreateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ShareBasicCreateLogic {
    16. return &ShareBasicCreateLogic{
    17. Logger: logx.WithContext(ctx),
    18. ctx: ctx,
    19. svcCtx: svcCtx,
    20. }
    21. }
    22. func (l *ShareBasicCreateLogic) ShareBasicCreate(req *types.ShareBasicCreateRequest, userIdentity string) (resp *types.ShareBasicCreateReply, err error) {
    23. // todo: add your logic here and delete this line
    24. uuid := helper.GetUUID()
    25. data := &Models.ShareBasic{
    26. Identity: uuid,
    27. UserIdentity: userIdentity,
    28. RepositoryIdentity: req.RepositoryIdentity,
    29. ExpiredTime: req.ExpiredTime,
    30. }
    31. _, err = l.svcCtx.Engine.Insert(data)
    32. if err != nil {
    33. return
    34. }
    35. resp = &types.ShareBasicCreateReply{
    36. Identity: uuid,
    37. }
    38. return
    39. }

    ②获取资源详情

    对于这个模块,就不用登录的中间件了,因为未登录的应该也可以获取到别人分享的文件。所以就写在用户登录等的那个api块里就行。

    code.api

    1. //获取资源详情
    2. @handler ShareBasicDetail
    3. get /share/basic/detail (ShareBasicDetailRequest) returns (ShareBasicDetailReply)
    4. type ShareBasicDetailRequest {
    5. Identity string `json:"identity"`
    6. }
    7. type ShareBasicDetailReply {
    8. RepositoryIdentity string `json:"repository_identity"`
    9. Name string `json:"name"`
    10. Ext string `json:"ext"`
    11. Size int64 `json:"size"`
    12. Path string `json:"path"`
    13. }

    Models

    1. package Models
    2. import "time"
    3. type ShareBasic struct {
    4. Id int
    5. Identity string
    6. UserIdentity string
    7. RepositoryIdentity string
    8. ExpiredTime int
    9. ClickNum int
    10. CreatedAt time.Time `xorm:"created"`
    11. UpdatedAt time.Time `xorm:"updated"`
    12. DeletedAt time.Time `xorm:"deleted"`
    13. }
    14. func (table ShareBasic)TableName( ) string {
    15. return "share_basic"
    16. }

    logic

    1. package logic
    2. import (
    3. "context"
    4. "CloudDisk/code/internal/svc"
    5. "CloudDisk/code/internal/types"
    6. "github.com/zeromicro/go-zero/core/logx"
    7. )
    8. type ShareBasicDetailLogic struct {
    9. logx.Logger
    10. ctx context.Context
    11. svcCtx *svc.ServiceContext
    12. }
    13. func NewShareBasicDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ShareBasicDetailLogic {
    14. return &ShareBasicDetailLogic{
    15. Logger: logx.WithContext(ctx),
    16. ctx: ctx,
    17. svcCtx: svcCtx,
    18. }
    19. }
    20. func (l *ShareBasicDetailLogic) ShareBasicDetail(req *types.ShareBasicDetailRequest) (resp *types.ShareBasicDetailReply, err error) {
    21. // todo: add your logic here and delete this line
    22. //对分享记录的点击次数进行 +1 操作
    23. _, err = l.svcCtx.Engine.Exec("UPDATE share_basic SET click_num = click_num + 1 WHERE identity = ?", req.Identity)
    24. if err!=nil {
    25. return
    26. }
    27. //获取资源的详细信息
    28. resp= new(types.ShareBasicDetailReply)
    29. _, err = l.svcCtx.Engine.Table("share_basic").
    30. Select("share_basic.repository_identity,repository_pool.name,repository_pool.ext,repository_pool.size,repository_pool.path").
    31. Join("LEFT", "repository_pool", "share_basic.repository_identity=repository_pool.identity").
    32. Where("share_basic.identity=?", req.Identity).Get(resp)
    33. return
    34. }

    ③资源保存

    需要用户登录的中间件,code.api 

    1. //资源保存
    2. @handler ShareBasicSave
    3. post /share/basic/save (ShareBasicSaveRequest) returns (ShareBasicSaveReply)
    4. type ShareBasicSaveRequest {
    5. RepositoryIdentity string `json:"repository_identity"`
    6. ParentId int64 `json:"parent_id"`
    7. }
    8. type ShareBasicSaveReply {
    9. Identity string `json:"identity"`
    10. }

    logic

    1. package logic
    2. import (
    3. "CloudDisk/code/Models"
    4. "CloudDisk/code/helper"
    5. "context"
    6. "errors"
    7. "CloudDisk/code/internal/svc"
    8. "CloudDisk/code/internal/types"
    9. "github.com/zeromicro/go-zero/core/logx"
    10. )
    11. type ShareBasicSaveLogic struct {
    12. logx.Logger
    13. ctx context.Context
    14. svcCtx *svc.ServiceContext
    15. }
    16. func NewShareBasicSaveLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ShareBasicSaveLogic {
    17. return &ShareBasicSaveLogic{
    18. Logger: logx.WithContext(ctx),
    19. ctx: ctx,
    20. svcCtx: svcCtx,
    21. }
    22. }
    23. func (l *ShareBasicSaveLogic) ShareBasicSave(req *types.ShareBasicSaveRequest,userIdentity string) (resp *types.ShareBasicSaveReply, err error) {
    24. // todo: add your logic here and delete this line
    25. //获取资源详情
    26. rp:=new(Models.RepositoryPool)
    27. has, err := l.svcCtx.Engine.Where("identity=?", req.RepositoryIdentity).Get(rp)
    28. if err!=nil {
    29. return nil, err
    30. }
    31. if !has {
    32. return nil,errors.New("资源不存在")
    33. }
    34. //user_repository 资源保存
    35. ur:=&Models.UserRepository{
    36. Identity: helper.GetUUID(),
    37. UserIdentity: userIdentity,
    38. ParentId: req.ParentId,
    39. RepositoryIdentity: req.RepositoryIdentity,
    40. Ext: rp.Ext,
    41. Name: rp.Name,
    42. }
    43. _, err = l.svcCtx.Engine.Insert(ur)
    44. resp=new(types.ShareBasicSaveReply)
    45. resp.Identity=ur.Identity
    46. return
    47. }
  • 相关阅读:
    长城新能源汽车,战力已蓄满
    Apache Sqoop_2
    使用 GRPC C++ API连接Java的RPC服务
    拙见--springMVC的controller接受的请求参数
    能不能绕过c去学c++?
    C进阶 - 指针进阶
    虹科案例 | 增量式编码器&紧急停止开关之案例研究(下)
    2022年湖北工业大学招生简章之高起专、专升本非全日制学历提升
    哪个牌子除甲醛产品效果好 目前除甲醛最好的净化器
    Python数据类型 ——— 字典
  • 原文地址:https://blog.csdn.net/m0_51530927/article/details/128050856