这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天
package main
import (
"io"
"log"
"net/http"
"os"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Video struct {
gorm.Model
Name string
URL string
}
func main() {
// 连接数据库
dsn := "root:password@tcp(127.0.0.1:3306)/video_stream?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
// 自动迁移数据库结构
db.AutoMigrate(&Video{})
// 创建 gin 实例
r := gin.Default()
// 定义视频流的接口
r.GET("/stream/:name", func(c *gin.Context) {
name := c.Param("name")
var video Video
if err := db.Where("name = ?", name).First(&video).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "视频不存在"})
return
}
// 打开视频文件
file, err := os.Open(video.URL)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "打开视频文件失败"})
return
}
defer file.Close()
// 设置响应头
c.Header("Content-Type", "video/mp4")
c.Header("Content-Disposition", "attachment;filename="+name+".mp4")
// 将视频流复制到响应体中
if _, err := io.Copy(c.Writer, file); err != nil {
log.Println(err)
}
})
// 启动 Web 服务
r.Run(":8080")
}
定义了一个 Video 结构体,用于表示数据库中的视频。然后连接数据库,并自动迁移数据库结构。
创建一个 gin 实例,并定义了一个 /stream/:name 的接口,用于返回指定名称的视频流。在这个接口中,从数据库中查询到指定名称的视频,并打开对应的视频文件。然后,我们设置响应头,将视频流复制到响应体中,并发送给客户端。
db.AutoMigrate(&Video{})
db.AutoMigrate(&Video{})是 GORM 的一个函数调用,用于自动迁移数据库结构,即在数据库中创建表格和字段。 在这个调用中,我们将&Video{}作为参数传递给AutoMigrate函数。这表示我们希望自动创建与Video结构体对应的数据表。如果该表已经存在,AutoMigrate函数也会检查表格结构是否需要更新,例如添加新的字段。 具体来说,当我们使用db.AutoMigrate(&Video{})时,GORM 会执行以下操作:
- 检查数据库中是否存在名为
videos的表格。如果不存在,则创建该表格;- 检查
videos表格中是否存在id,created_at,updated_at和deleted_at这些字段。如果.不存在,则创建这些字段;- 检查
videos表格中是否存在name和url字段。如果不存在,则创建这些字段。