视频上传接口实现|青训营

95 阅读5分钟

代码设计思路解析

  1. 导入包和结构体定义: 代码首先导入所需的包,包括Gin框架、GORM库等。同时,定义了用于API响应的结构体 VideoListResponse 和用于数据库操作的结构体 token
type VideoListResponse struct {
    Response
    VideoList []Video `json:"video_list"`
}

type token struct {
    UserId int64  `json:"user_id,omitempty"gorm:"primaryKey;autoIncrement"`
    Token  string `json:"token"`
}
  1. 提取视频封面图像函数 extractVideoCover 这个函数的主要功能是从上传的视频文件中提取封面图像。它构建了封面图像的文件路径,并通过命令行工具 ffmpeg 对视频文件进行截图。然后,生成封面图像的URL并返回。这样的设计允许系统在发布视频时自动生成封面图像,增强用户体验。
func extractVideoCover(videoFilePath string) (string, error) {

    coverFileName := fmt.Sprintf("%s_cover.jpg", filepath.Base(videoFilePath))
    coverFilePath := filepath.Join("./public/cover/", coverFileName) // 可自定义保存路径

    cmd := exec.Command("ffmpeg", "-i", videoFilePath, "-ss", "00:00:01", "-vframes", "1", coverFilePath)
    output, err := cmd.CombinedOutput()
    if err != nil {
       return "", fmt.Errorf("截取封面图像出错: %v\n%s", err, output)
    }

    coverurl := fmt.Sprintf("http://%s:8080/cover/%s", getLocalIP(), coverFileName)
    fmt.Println("生成封面图像成功:", coverFilePath)
    return coverurl, nil
}
  1. 处理视频发布请求的函数 Publish 这个函数处理用户发布视频的请求。首先,它从请求中获取用户令牌,并尝试连接到数据库。通过令牌查询数据库,如果找到匹配的记录,则获取用户信息。

    接下来,它接收上传的视频文件,为其生成一个唯一的文件名,并将文件保存到指定路径。然后,调用前面定义的 extractVideoCover 函数来获取视频封面图像URL。

    最后,将视频信息和封面URL存入数据库,完成视频发布。这样的设计考虑了用户身份验证、视频存储和封面图像生成的方方面面,构建了完整的视频发布流程。

func Publish(c *gin.Context) {
    utoken := c.PostForm("token")

    dsn := "host=localhost user=postgres password=281455 dbname=tiktok port=5432 sslmode=disable TimeZone=Asia/Shanghai"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
       panic("无法连接数据库")
    }

    token := token{}

    result := db.First(&token, "token = ?", utoken)
    if result.Error != nil {
       if result.Error == gorm.ErrRecordNotFound {
          c.JSON(http.StatusOK, Response{StatusCode: 1, StatusMsg: "User doesn't exist"})
       } else {
          // 处理其他错误情况
       }
    } else {
       // 处理找到记录的情况
    }

    user := User{}

    db.Select("id, name, follow_count, follower_count, is_follow").
       Where("Id = ?", token.UserId).First(&user)

    data, err := c.FormFile("data")
    if err != nil {
       c.JSON(http.StatusOK, Response{
          StatusCode: 1,
          StatusMsg:  err.Error(),
       })
       return
    }

    filename := filepath.Base(data.Filename)

    finalName := fmt.Sprintf("%d_%s", user.Id, filename)

    saveFile := filepath.Join("./public/videos/", finalName)
    if err := c.SaveUploadedFile(data, saveFile); err != nil {
       c.JSON(http.StatusOK, Response{
          StatusCode: 1,
          StatusMsg:  err.Error(),
       })
       return
    }

    cover, err := extractVideoCover(saveFile)
    if err != nil {
       c.JSON(http.StatusOK, Response{
          StatusCode: 1,
          StatusMsg:  err.Error(),
       })
       return
    }

    playurl := fmt.Sprintf("http://%s:8080/video/%s", getLocalIP(), finalName)
    video := Videos{
       AuthorID:      user.Id,
       PlayUrl:       playurl,
       CoverUrl:      cover,
       FavoriteCount: 0,
       CommentCount:  0,
       IsFavorite:    false,
    }

    if err := db.Create(&video).Error; err != nil {
       c.JSON(http.StatusOK, Response{
          StatusCode: 1,
          StatusMsg:  err.Error(),
       })
       return
    }
    sqlDB, _ := db.DB()
    defer sqlDB.Close()

    c.JSON(http.StatusOK, Response{
       StatusCode: 0,
       StatusMsg:  finalName + " uploaded successfully",
    })
}
  1. 处理用户视频列表请求的函数 PublishList 这个函数用于获取用户发布的视频列表。通过令牌查询数据库,找到匹配的用户记录。然后,根据用户ID查询数据库,获取该用户发布的视频列表。
func PublishList(c *gin.Context) {

    dsn := "host=localhost user=postgres password=281455 dbname=tiktok port=5432 sslmode=disable TimeZone=Asia/Shanghai"
    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
    if err != nil {
       panic("无法连接数据库")
    }
    utoken := c.PostForm("token")

    var tokenRecord token
    tokenResult := db.Where("token = ?", utoken).First(&tokenRecord)
    if tokenResult.Error != nil {
       if tokenResult.Error == gorm.ErrRecordNotFound {
          c.JSON(http.StatusOK, Response{StatusCode: 1, StatusMsg: "Token not found"})
       } else {
          // 处理其他错误情况
       }
       return
    }

    var publishvideos = []Video{}
    var pdbvideolist = []Videos{}

    db.Where("authorid = ?", tokenRecord.UserId).Find(&pdbvideolist)

    for _, pdbvideolist := range pdbvideolist {
       var user User
       db.Select("id, name, follow_count, follower_count, is_follow").
          Where("Id = ?", pdbvideolist.AuthorID).First(&user)

       video := Video{
          Id:            pdbvideolist.Id,
          Author:        user,
          PlayUrl:       pdbvideolist.PlayUrl,
          CoverUrl:      pdbvideolist.CoverUrl,
          FavoriteCount: pdbvideolist.FavoriteCount,
          CommentCount:  pdbvideolist.CommentCount,
          IsFavorite:    pdbvideolist.IsFavorite,
       }

       publishvideos = append(publishvideos, video)
    }

    c.JSON(http.StatusOK, VideoListResponse{
       Response: Response{
          StatusCode: 0,
       },
       VideoList: publishvideos,
    })
}
在循环中,它从数据库获取视频信息,并构建了一个用于响应的视频列表。这样的设计为用户提供了一个查看自己发布视频列表的功能,丰富了系统的功能。
  1. 获取本地IP地址的函数 getLocalIP 这个函数用于获取本地IP地址。它遍历网络接口地址,找到第一个非回环的IPv4地址,并返回。
func getLocalIP() string {
    addrs, err := net.InterfaceAddrs()
    if err != nil {
       return ""
    }

    // 遍历接口地址
    for _, addr := range addrs {
       ipnet, ok := addr.(*net.IPNet)
       if ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
          // 如果满足条件,返回找到的第一个合适的地址
          return ipnet.IP.String()
       }
    }

    return "" // 没有找到符合条件的地址
}

个人思考与学习笔记

这份代码展示了一个基本的视频发布与展示系统的实现,使用了Gin框架和GORM库。通过代码的解析,我对以下方面进行了思考和学习:

  1. Web框架和数据库库的使用: 通过阅读代码,我了解了如何使用Gin框架处理HTTP请求和路由,以及如何使用GORM库进行数据库操作。这让我更深入地理解了Web开发和数据库连接的过程。
  2. 视频封面图像的自动生成: 通过 extractVideoCover 函数,我学到了如何使用命令行工具生成视频封面图像,并将其与视频关联。这个自动生成的设计有助于提升用户体验,同时减轻了用户的操作负担。
  3. 用户身份验证和数据关联: 代码中通过令牌对用户进行身份验证,然后将用户信息与视频关联。这种关联设计在构建复杂系统时非常重要,它可以帮助维护数据的一致性和完整性。
  4. 错误处理和异常情况: 代码中充分考虑了可能的错误情况,比如数据库连接失败、文件上传失败等。这样的错误处理设计是保障系统稳定性的关键。
  5. 系统功能的实现: 代码展示了视频发布和展示系统的基本功能,包括视频上传、封面图像生成、用户视频列表等。我意识到在实际项目中,需要综合考虑用户需求,实现更多的功能和交互。