beego不提供音乐播放功能,需自行实现播放列表crud接口及音频文件服务;playlist与playlistitem应分表设计,用外键关联,避免json数组存储;路由注册须从细到粗,controller中须手动解析:id参数并调用c.servejson(),静态音频路径需正确配置staticdir且防范路径遍历。

Beego 本身不提供音乐播放功能,也不内置播放列表管理逻辑——它只是个 Web 框架,所有播放控制、音频解码、前端播放器交互都得靠你自己组织。真正的关键点是:如何用 Beego 正确暴露播放列表的 CRUD 接口,并安全地服务音频文件。
播放列表数据结构怎么设计才适合 Beego ORM
Beego 的 orm 对 struct tag 依赖强,字段命名和类型稍有偏差就查不到数据或报错。播放列表不是简单数组,而应拆成两个模型:一个存歌单(Playlist),一个存歌曲条目(PlaylistItem),用外键关联。
常见错误是把歌曲路径直接塞进 JSON 数组字段里,结果没法按歌手查、没法加播放次数统计、没法做事务回滚。
-
Playlist必须含Id(int64)、Name(string)、CreatedAt(time.Time);type字段别用string存 “public”/“private”,改用int8+ 常量映射,避免拼写错误导致权限失控 -
PlaylistItem要有PlaylistId(int64)、SongId(int64)、OrderNum(int),别用Position或Index这类易混淆名 - 音频文件路径统一存在独立
Song表里,字段叫FilePath,值必须是相对static/audio/的路径(如"rock/2023/hello.mp3"),不能是绝对路径或 URL,否则beego.BConfig.WebConfig.StaticDir配置会失效
为什么 /api/playlist/:id/items 返回空?排查路由和 Controller 写法
Beego 默认不自动解析嵌套路由参数,:id 不会自动绑定到 Controller 方法参数里。你写的 GetItems() 方法如果没手动调 c.Ctx.Input.Param(":id"),拿到的就是空字符串,查库当然没结果。
更隐蔽的问题是:Beego 的 URLMapping 是前缀匹配,如果你注册了 /api/playlist/:id 和 /api/playlist/:id/items 两条规则,但顺序反了,后者永远进不了——因为前者先匹配成功,:id 吃掉了整个路径段。
- 在
router.go中严格按从细到粗顺序注册:ns.Get("/api/playlist/:id/items", (*PlaylistController)(nil).GetItems)必须在ns.Get("/api/playlist/:id", ...)之前 -
GetItems方法里必须用c.Ctx.Input.Param(":id")拿 ID,转int64时要检查错误,别直接strconv.ParseInt(..., 10, 64)后忽略 err - 别在
GetItems里用c.Data["json"] = items后忘掉c.ServeJSON()——Beego 不会自动触发序列化
前端请求 /audio/rock/2023/hello.mp3 404?检查静态文件配置和路径安全
Beego 默认只开放 static 目录下的文件,且对路径做白名单过滤。如果你把音频放在 static/audio/ 下,但请求的是 /audio/...,而没在 app.conf 里配 StaticDir = "audio: static/audio",就会 404。
更大的风险是路径遍历:用户若构造 /audio/../../../etc/passwd,Beego 旧版本(
- 在
conf/app.conf中显式声明:StaticDir = "audio: static/audio",不要依赖默认的static映射 - 音频文件路径入库前,用
filepath.Clean()处理并校验是否以"audio/"开头,拒绝含".."或绝对路径的输入 - 别用
http.ServeFile手动读取文件返回,改用 Beego 的静态路由机制,它内置了安全检查
真正难的不是写几个接口,而是确保每首歌的 FilePath 在数据库、磁盘路径、HTTP 路由三者之间始终一致,且不因大小写、编码、空格或 Windows/Linux 路径分隔符差异出问题。这些细节在本地测不出,上线后第一个用户上传带中文名的 MP3 就崩。











