如何用Node.js+Multer将Blob URL转存为WebM/MP4视频到服务器
问题
通过HTML5录制视频得到Blob URL(如blob:http://localhost:3000/xxx),想用Node.js将视频上传至服务器。当前前端上传的是Blob URL字符串,后端用Multer接收时仅拿到URL而非视频数据,上传失败。如何将Blob URL转换为WebM/MP4视频并保存到服务器文件夹?
原代码展示
前端代码
camera_stream = await navigator.mediaDevices.getUserMedia({ video: true }); video.srcObject = camera_stream; media_recorder = new MediaRecorder(camera_stream, { mimeType: 'video/webm' }); media_recorder.addEventListener('dataavailable', function(e) { blobs_recorded.push(e.data); }); let video_local = URL.createObjectURL(new Blob(blobs_recorded, { type: 'video/webm' })); var fd = new FormData(); fd.append('name', 'test.webm'); fd.append('data', video_local); $.ajax({ type: 'POST', url: '/cam', data: fd, cache : false, contentType : false, processData : false }).done(function(data) { console.log('success'); });
Node.js及Multer代码
router.post('/cam',upload.single("data"),(req,res)=>{ console.log(req.body); })
当前Multer输出结果
[Object: null prototype] { name: 'test.webm', data: 'blob:http://localhost:3000/a1ce2f38-2cc1-4216-979b-90e574d11b75' }
原因分析
Blob URL只是浏览器生成的本地临时引用,本质是字符串,并非实际的视频文件数据。直接上传这个URL,后端自然无法获取到视频内容。
解决方案
前端修改:直接上传Blob对象
不需要生成Blob URL,直接把录制得到的Blob(或合并后的Blob)添加到FormData中,Multer才能识别为文件。
修改后的前端代码:
camera_stream = await navigator.mediaDevices.getUserMedia({ video: true }); video.srcObject = camera_stream; media_recorder = new MediaRecorder(camera_stream, { mimeType: 'video/webm' }); const blobs_recorded = []; media_recorder.addEventListener('dataavailable', function(e) { blobs_recorded.push(e.data); }); // 录制停止后触发上传逻辑 media_recorder.stop(); media_recorder.addEventListener('stop', function() { // 合并所有录制片段为完整视频Blob const videoBlob = new Blob(blobs_recorded, { type: 'video/webm' }); var fd = new FormData(); // 直接传入Blob对象,第三个参数指定文件名 fd.append('data', videoBlob, 'test.webm'); $.ajax({ type: 'POST', url: '/cam', data: fd, cache: false, contentType: false, processData: false }).done(function(data) { console.log('上传成功'); }).fail(function(err) { console.error('上传失败', err); }); });
后端修改:配置Multer保存文件
配置Multer的存储规则,指定视频保存的目录和文件名,确保上传的文件能被正确保存。
修改后的Node.js代码:
const express = require('express'); const router = express.Router(); const multer = require('multer'); const fs = require('fs'); // 配置Multer存储参数 const storage = multer.diskStorage({ destination: function (req, file, cb) { // 确保uploads目录存在,不存在则创建 const uploadDir = './uploads'; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir); } cb(null, uploadDir); }, filename: function (req, file, cb) { // 生成唯一文件名,避免重复 const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); const ext = file.originalname.split('.').pop(); cb(null, `video-${uniqueSuffix}.${ext}`); } }); const upload = multer({ storage: storage }); router.post('/cam', upload.single("data"), (req, res) => { // req.file包含上传文件的完整信息 console.log('文件信息:', req.file); res.json({ status: 'success', message: '视频上传完成', savePath: req.file.path }); }); module.exports = router;
验证结果
修改完成后,后端req.file会输出类似如下的文件信息,视频文件将自动保存到./uploads目录下:
{ fieldname: 'data', originalname: 'test.webm', encoding: '7bit', mimetype: 'video/webm', destination: './uploads', filename: 'video-1700000000000-123456789.webm', path: 'uploads/video-1700000000000-123456789.webm', size: 896542 // 文件字节大小 }
内容的提问来源于stack exchange,提问作者Cihan Sulu
相关产品推荐
相关产品推荐

