如何使用Express.js实现视频上传至MongoDB的API?
实现视频上传至MongoDB的API方案
核心前提
MongoDB的普通BSON文档最大仅支持16MB存储,视频文件通常远超这个限制,所以必须使用GridFS来存储大文件——它会自动将文件拆分为256KB的分片存储,同时保留文件的元数据。下面以Node.js + Express + Mongoose栈为例,给出具体实现步骤:
1. 环境依赖安装
首先安装所需的npm包:
npm install express mongoose multer multer-gridfs-storage
express: 搭建Web服务mongoose: MongoDB的ODM框架multer: 处理multipart/form-data类型的文件上传multer-gridfs-storage: 基于multer的GridFS存储引擎
2. 初始化MongoDB连接与GridFS配置
创建db.js文件,配置数据库连接和GridFS存储:
const mongoose = require('mongoose'); const Grid = require('gridfs-stream'); const GridFsStorage = require('multer-gridfs-storage'); // MongoDB连接字符串 const mongoURI = 'mongodb://localhost:27017/video_upload_db'; // 连接数据库 const conn = mongoose.createConnection(mongoURI); // 初始化GridFS let gfs; conn.once('open', () => { gfs = Grid(conn.db, mongoose.mongo); gfs.collection('videos'); // 指定存储视频的集合名 }); // 配置multer的GridFS存储引擎 const storage = new GridFsStorage({ url: mongoURI, file: (req, file) => { // 自定义文件元数据和存储信息 return new Promise((resolve, reject) => { const filename = `${Date.now()}-${file.originalname}`; const fileInfo = { filename: filename, bucketName: 'videos', // 对应上面的GridFS集合名 metadata: { uploader: req.user?.id, // 可选:存储上传用户ID(需结合权限验证) originalName: file.originalname } }; resolve(fileInfo); }); } }); const upload = require('multer')({ storage }); module.exports = { conn, gfs, upload };
3. 编写视频上传API接口
创建routes/videos.js文件,实现上传接口:
const express = require('express'); const router = express.Router(); const { upload } = require('../db'); // POST /api/videos/upload - 上传视频 router.post('/upload', upload.single('video'), (req, res) => { // req.file包含上传后的文件元数据 if (!req.file) { return res.status(400).json({ error: '未选择视频文件' }); } res.status(200).json({ message: '视频上传成功', fileId: req.file.id, filename: req.file.filename, originalName: req.file.metadata.originalName }); }); module.exports = router;
然后在主文件app.js中挂载路由:
const express = require('express'); const app = express(); const videoRoutes = require('./routes/videos'); app.use('/api/videos', videoRoutes); const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`服务运行在端口${PORT}`));
4. 编写视频获取/播放API接口
在routes/videos.js中添加获取接口,支持流式返回视频:
const { gfs } = require('../db'); // GET /api/videos/:filename - 根据文件名获取视频 router.get('/:filename', (req, res) => { gfs.files.findOne({ filename: req.params.filename }, (err, file) => { if (!file || file.length === 0) { return res.status(404).json({ error: '视频不存在' }); } // 检查文件是否为视频类型 if (file.contentType.startsWith('video/')) { // 创建可读流 const readstream = gfs.createReadStream(file.filename); readstream.pipe(res); } else { res.status(400).json({ error: '不是视频文件' }); } }); }); // 可选:根据文件ID获取视频 router.get('/id/:id', (req, res) => { gfs.files.findOne({ _id: req.params.id }, (err, file) => { if (!file || file.length === 0) { return res.status(404).json({ error: '视频不存在' }); } if (file.contentType.startsWith('video/')) { const readstream = gfs.createReadStream(file._id); readstream.pipe(res); } else { res.status(400).json({ error: '不是视频文件' }); } }); });
5. 关键注意事项
- 文件校验:可以在multer的file配置中添加视频格式校验,只允许
mp4、mov等格式:file: (req, file) => { const allowedTypes = ['video/mp4', 'video/mov', 'video/webm']; if (!allowedTypes.includes(file.mimetype)) { return reject(new Error('仅支持MP4、MOV、WEBM格式的视频')); } // ... 其余代码 } - 性能优化:GridFS适合存储视频,但直接从MongoDB流式返回可能影响性能,建议配合CDN缓存已上传的视频,或者将视频存储到对象存储,仅在MongoDB中保存视频的元数据和访问链接。
- 权限控制:上传和获取接口需添加用户身份验证(如JWT),确保只有授权用户能上传或访问特定视频。
- 文件大小限制:在multer配置中设置文件大小上限,避免超大文件占用资源:
const upload = require('multer')({ storage, limits: { fileSize: 100 * 1024 * 1024 } // 限制100MB });
内容的提问来源于stack exchange,提问作者Arijit das
相关产品推荐
相关产品推荐

