短剧平台需实现断点续播与防盗链:通过play.php动态鉴权(校验user_id、上架状态及1小时内有效token),流式输出视频并禁用缓存;前端防抖上报进度,后端用mysql复合主键表安全存储;新页面加载时自动获取并跳转至上次播放位置。

短剧平台需在用户切换设备或刷新页面后,继续从上次中断处播放,同时确保未付费用户无法直接下载或盗链视频资源。这要求后端既完成动态鉴权又可靠记录播放进度,二者必须解耦但协同生效。
用play.php实现带Token的流式鉴权
将所有视频文件移出Web根目录,例如放到/data/videos/short/,禁止Nginx或Apache直接访问该路径。
创建app/controller/Play.php控制器,定义index方法接收video_id和token参数。
校验token时必须同时验证三要素:【user_id存在且已登录】、video_id对应短剧是否已上架、token是否由sha256($video_id.$user_id.$timestamp.$secret)生成且$timestamp未超1小时。
通过验证后,根据video_id查出真实物理路径(如/data/videos/short/1024.mp4),调用分块流式输出逻辑——不使用readfile(),改用fopen()+fread()配合header('Accept-Ranges: bytes')和Content-Range响应头,确保拖拽正常。
最后在响应头中添加Cache-Control: no-store, no-cache,禁用CDN与浏览器缓存。
前端每5秒上报播放进度
在短剧播放页的<video></video>元素绑定timeupdate事件,但不要无脑监听——先用防抖函数限制为最多每5秒触发一次。
每次触发时,读取video.currentTime并四舍五入取整秒值,连同user_id、video_id一起POST到/api/v1/progress/save接口。
注意:当用户拖动进度条后,timeupdate会高频触发,此时应忽略前几次,只在seeked事件后强制上报一次最新位置,避免脏数据覆盖。
后端安全存储播放进度
第一步:在MySQL中建表user_video_progress,主键设为(user_id, video_id)复合主键,字段含current_time INT UNSIGNED和updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。
第二步:接收前端POST后,先校验user_id与当前session一致,再执行以下SQL:
INSERT INTO user_video_progress (user_id, video_id, current_time) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE current_time = VALUES(current_time), updated_at = NOW();
第三步:返回JSON中包含"saved": true及服务端写入的updated_at时间戳,供前端做粗略时钟对齐。
严禁用file_put_contents()写文件存进度——并发写入时极易丢失数据,且无事务保障。
新页面加载时自动续播
方法一:页面初始化时,向/api/v1/progress/get?video_id=1024发起GET请求,后端查user_video_progress表并返回current_time值;前端拿到后立即设置video.currentTime = res.data.current_time,再调用video.play()。
方法二:若短剧页采用SSR(如ThinkPHP8 + Vue SSR),可在控制器中提前查出进度值,注入到模板初始数据中,避免首屏白屏等待API返回。
两种方法都需注意:若查不到记录,返回current_time: 0,不要抛错或中断播放流程。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











