使用Node.js结合Multer上传视频至Cloudinary时持续触发Error 400 "Invalid image file"错误求助
使用Node.js结合Multer上传视频至Cloudinary时持续触发Error 400 "Invalid image file"错误求助
嘿,我仔细看了你的问题和代码,这个错误确实挺闹心的——明明传的是MP4视频,Cloudinary却一直把它当成无效图片。咱们一步步来排查和修复:
首先,修复Multer文件过滤器的逻辑bug
你的videoFileFilter里有个明显的逻辑问题:当文件类型不符合要求时,你先调用了cb("Supports only video files!", false),但之后又执行了cb(null, true),这会导致Multer接收到两次回调,逻辑混乱,甚至可能让不符合要求的文件被错误放行,或者引发文件处理异常。
把过滤器改成这样,确保不符合条件时直接终止后续代码:
const videoFileFilter=(req, file, cb) => { if(file.mimetype!=="video/mp4"){ // 用return终止函数,避免执行后续的cb(null, true) return cb("Supports only video files!", false); } cb(null, true); };
然后,排查Cloudinary上传的配置细节
虽然你已经设置了resource_type: "video",但咱们可以从几个方向验证优化:
1. 确认本地文件路径的有效性
在上传到Cloudinary之前,先检查临时文件是否存在,避免因为路径错误导致Cloudinary读取失败:
const fs = require('fs'); exports.uploadTrailer = async (req, res,next) => { const { file } = req; console.log(file) try{ if (!file) return sendError(res, "Video file is missing!"); // 新增:检查文件是否存在 if (!fs.existsSync(file.path)) { return sendError(res, "Uploaded video file not found!"); } const { secure_url: url, public_id } = await cloudinary.uploader.upload( file.path, { resource_type: "video", // 额外指定格式,确保Cloudinary正确识别文件类型 format: "mp4" } ); res.status(201).json({ url, public_id }); } catch(error){ console.log(error) next(error) } };
2. 尝试使用流式上传替代本地文件路径
有时候磁盘存储的临时文件可能因为权限、系统自动清理等问题导致Cloudinary读取异常,试试用流式上传的方式:
exports.uploadTrailer = async (req, res,next) => { const { file } = req; try{ if (!file) return sendError(res, "Video file is missing!"); // 使用Cloudinary的流式上传API const uploadStream = cloudinary.uploader.upload_stream( { resource_type: 'video', format: 'mp4' }, (error, result) => { if (error) { console.log(error); return next(error); } res.status(201).json({ url: result.secure_url, public_id: result.public_id }); } ); // 创建文件流并管道到Cloudinary require('fs').createReadStream(file.path).pipe(uploadStream); } catch(error){ console.log(error) next(error) } };
3. 尝试使用内存存储替代磁盘存储
如果流式上传还是不行,换用Multer的内存存储,直接传递文件buffer给Cloudinary:
// 修改multer配置里的storage为内存存储 const storage = multer.memoryStorage(); // 控制器里修改上传逻辑 exports.uploadTrailer = async (req, res,next) => { const { file } = req; try{ if (!file) return sendError(res, "Video file is missing!"); // 将buffer转为base64格式上传 const base64Video = `data:${file.mimetype};base64,${file.buffer.toString('base64')}`; const { secure_url: url, public_id } = await cloudinary.uploader.upload( base64Video, { resource_type: "video", format: "mp4" } ); res.status(201).json({ url, public_id }); } catch(error){ console.log(error) next(error) } };
最后,验证Cloudinary账号权限
虽然你能成功上传图片,但还是可以确认下你的Cloudinary账号是否允许视频上传——一般免费账号也支持视频上传,只是有容量限制,这个可能性比较低,但可以去Cloudinary控制台的设置里确认一下。
先修复过滤器的bug,再试试上面的上传方式,应该能解决这个问题!
备注:内容来源于stack exchange,提问作者mahir
相关产品推荐
相关产品推荐

