PHP不应将视频文件存入数据库BLOB字段,而应只存储路径或URL及元数据;video_path用VARCHAR(512)并加索引,上传时用move_uploaded_file存磁盘或对象存储,校验需finfo_open而非$_FILES['type']。

PHP 不适合直接把视频文件存进数据库,二进制大对象(BLOB)会严重拖慢查询、备份和迁移——真正该存的是视频的元数据和访问路径。
只存视频路径,不存视频文件本身
绝大多数业务场景下,video_path 字段应为相对或绝对文件系统路径(如 /uploads/videos/20240512_abc123.mp4),或 CDN/对象存储 URL(如 https://cdn.example.com/videos/abc123.mp4)。数据库里只需记录这些字符串,配合 file_exists() 或 HTTP HEAD 请求做存在性校验即可。
常见错误:把 $_FILES['video']['tmp_name'] 直接用 file_get_contents() 读成字符串塞进 MEDIUMBLOB 字段,结果上传 100MB 视频时 PHP 内存溢出、MySQL 报 Packet too large 错误。
- 上传后立刻用
move_uploaded_file()存到磁盘或上传至 OSS/S3 - 数据库只插入
filename、mime_type、size_bytes、uploaded_at和storage_type(如'local'或'oss') - 避免在 SQL 中拼接完整路径,路径生成逻辑统一收口在 PHP 层
MySQL 字段类型选 VARCHAR(512),别用 TEXT 或 BLOB
VARCHAR(512) 足够存任何合理长度的路径或 URL;TEXT 类型会导致索引失效(除非加前缀索引)、排序变慢;BLOB 更是完全错误的方向——它不支持索引、无法被 WHERE 条件高效过滤,且备份时体积暴增。
立即学习“PHP免费学习笔记(深入)”;
建表示例:
CREATE TABLE videos ( id INT PRIMARY KEY AUTO_INCREMENT, filename VARCHAR(255) NOT NULL, video_path VARCHAR(512) NOT NULL, mime_type VARCHAR(64) NOT NULL, size_bytes BIGINT UNSIGNED NOT NULL, uploaded_at DATETIME DEFAULT CURRENT_TIMESTAMP );
- 确保
video_path字段加索引:ALTER TABLE videos ADD INDEX idx_video_path (video_path); - 如果常按用户查视频,加联合索引:
(user_id, uploaded_at) - 不要为
mime_type或size_bytes单独建索引,除非有明确查询需求
上传时必须校验文件类型和大小,不能只信 $_FILES['video']['type']
$_FILES['video']['type'] 是浏览器传来的 MIME,可被任意伪造。真实校验要靠 finfo_open() 读取二进制头:
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['video']['tmp_name']);
finfo_close($finfo);
if (!in_array($mime, ['video/mp4', 'video/webm', 'video/quicktime'])) {
die('不支持的视频格式');
}
- 同时检查
$_FILES['video']['size']是否超过upload_max_filesize和post_max_size - 用
pathinfo($_FILES['video']['name'], PATHINFO_EXTENSION)提取扩展名,与 MIME 做双重比对 - 生成唯一文件名(如
uniqid() . '.' . $ext),防止覆盖或路径遍历
真正麻烦的从来不是“怎么存”,而是“怎么管”:视频文件没人清理、路径硬编码在模板里、CDN 缓存没配 TTL、删除记录时忘了删物理文件——这些才是线上事故高发点。











