【发布时间】:2021-02-11 15:21:15
【问题描述】:
我正在尝试更新和验证由两个文件输入(一个视频和一个用作视频缩略图的图像)和两个文本输入组成的表单。 当我上传单个文件时,验证器和 convertFiletoField 工作正常,但是它们都停止工作了,这是一个很长的问题,但如果有人能提供帮助,我将不胜感激。
我正在使用 Node、epxress、mongodb 和 express-validator v.5.1.2
路线:
router.get('/mvs', mvController.index);
router.get('/mvs/create', mvController.create);
router.post('/mvs/create',
uploadVideo.fields([{
name: 'videos', maxCount: 1
}, {
name: 'images', maxCount: 1
}]),
convertFileToField.videoHandle,
mvValidator.handle(),
mvController.store
);
router.get('/mvs/:id/edit', mvController.edit);
router.put('/mvs/:id',
uploadVideo.fields([{
name: 'videos', maxCount: 1
}, {
name: 'images', maxCount: 1
}]),
convertFileToField.videoHandle,
mvValidator.handle(),
mvController.update
);
router.delete('/mvs/:id', mvController.destroy);
控制器:
const fs = require('fs');
const path = require('path');
const controller = require('app/http/controllers/controller');
const Artist = require('app/models/artist');
const MV = require('app/models/mv');
class mvController extends controller {
async index(req , res) {
try {
let page = req.query.page || 1;
let mvs = await MV.paginate({} , { page , sort : { createdAt : 1 } , limit : 5 });
res.render('admin/mvs/index', { title : 'videos' , mvs });
} catch (err) {
next(err);
}
}
async create(req , res) {
let artists = await Artist.find({});
res.render('admin/mvs/create' , { artists });
}
async store(req , res , next) {
try {
let status = await this.validationData(req);
if(! status) {
if(req.file)
fs.unlinkSync(req.file.path);
return this.back(req,res);
}
// Create music video
let videos = this.videoPath(req.files['videos'][0]);
let images = this.videoPath(req.files['images'][0]);
let { title, artist} = req.body;
let newMV = new MV({
title,
slug : this.slug(title),
artist,
videos,
images
});
await newMV.save();
// update artist Times
this.updateArtistTime(req.body.artist);
return res.redirect('/admin/mvs');
} catch(err) {
next(err);
}
}
async edit(req, res ,next) {
try {
this.isMongoId(req.params.id);
let mv = await MV.findById(req.params.id);
let artists = await Artist.find({});
if( ! mv ) this.error('video does not exist' , 404);
return res.render('admin/mvs/edit' , { mv , artists });
} catch (err) {
next(err);
}
}
async update(req, res , next) {
try {
let status = await this.validationData(req);
if(! status) {
if(req.files)
fs.unlinkSync(req.files.path);
return this.back(req,res);
}
let objForUpdate = {};
// check video
if(req.files) {
objForUpdate.videos = this.videoPath(req.files['videos'][0]);
objForUpdate.images = this.videoPath(req.files['images'][0]);
}
delete req.body.videos;
delete req.body.images;
objForUpdate.slug = this.slug(req.body.title);
let mv = await MV.findByIdAndUpdate(req.params.id , { $set : { ...req.body, ...objForUpdate }});
// prev artist time update
this.updateArtistTime(mv.artist);
// now artist time update
this.updateArtistTime(req.body.artist);
return res.redirect('/admin/mvs');
} catch(err) {
next(err);
}
}
async destroy(req , res , next) {
try {
this.isMongoId(req.params.id);
let mv = await MV.findById(req.params.id);
if( ! mv ) this.error('video does not exist' , 404);
let artistId = mv.artist;
// delete music videos
fs.unlinkSync(`./public${mv.videos}`);
fs.unlinkSync(`./public${mv.images}`)
mv.remove();
// artist time update
this.updateArtistTime(artistId);
return res.redirect('/admin/mvs');
} catch (err) {
next(err);
}
}
async updateArtistTime(artistId) {
let artist = await Artist.findById(artistId).populate('mvs').exec();
artist.set({ time : this.getTime(artist.mvs)});
await artist.save();
}
videoPath(video) {
let addressVideos = this.getUrlVideo(`${video.destination}/${video.filename}`);
return addressVideos;
}
getUrlVideo(dir) {
return dir.substring(8);
}
slug(title) {
return title.replace(/([^۰-۹آ-یa-z0-9]|-)+/g , "-")
}
}
module.exports = new mvController();
uploadVideo 助手
const multer = require('multer');
const mkdirp = require('mkdirp');
const fs = require('fs');
const getDirVideo = () => {
let year = new Date().getFullYear();
let month = new Date().getMonth() + 1;
let day = new Date().getDay();
return `./public/uploads/mvs/${year}/${month}/${day}`;
}
const videoStorage = multer.diskStorage({
destination : (req , file , cb) => {
let dir = getDirVideo();
mkdirp(dir , (err) => cb(null , dir))
},
filename : (req , file , cb) => {
let filePath = getDirVideo() + '/' + file.originalname;
console.log(filePath);
if(!fs.existsSync(filePath))
cb(null , file.originalname);
else
cb(null , Date.now() + '-' + file.originalname);
}
})
const uploadVideo = multer({
storage : videoStorage,
limits : {
fileSize : 1024 * 1024 * 40
}
});
module.exports = uploadVideo;
converFiletoField
videoHandle(req , res , next) {
if(! req.files) {
req.body.videos = undefined;
req.body.images = undefined;
}
else {
req.body.videos = req.files.videos[0].filename;
req.body.images = req.files.images[0].filename;
}
next();
}
验证器:
const validator = require('./validator');
const { check } = require('express-validator/check');
const Artist = require('app/models/artist');
const MV = require('app/models/mv');
const path = require('path');
class mvValidator extends validator {
handle() {
return [
check('title')
.isLength({ min : 3 })
.withMessage('title can not be less than 3 characters'),
check('artist')
.not().isEmpty()
.withMessage('related artist can not remain empty'),
check('videos')
.custom(async (value , { req }) => {
if(req.query._method === 'put' && value === undefined) return;
if(! value)
throw new Error('video can not remain empty');
let fileExt = ['.webm' , '.mp4' , '.flv' , '.avi'];
if(! fileExt.includes(path.extname(value)))
throw new Error('file extention is not acceptable');
}),
check('images')
.custom(async (value , { req }) => {
if(req.query._method === 'put' && value === undefined) return;
if(! value)
throw new Error('video thumbnail can not remain empty');
let fileExt = ['.png' , '.jpg' , '.jpeg' , '.svg'];
if(! fileExt.includes(path.extname(value)))
throw new Error('file extention is not acceptable')
})
]
}
slug(title) {
return title.replace(/([^۰-۹آ-یa-z0-9]|-)+/g , "-")
}
}
module.exports = new mvValidator();
我在尝试更新/编辑时遇到的错误
TypeError: Cannot read property '0' of undefined
at convertFileToField.videoHandle (test\app\http\middleware\convertFileToField.js:22:47)
at Layer.handle [as handle_request] (test\node_modules\express\lib\router\layer.js:95:5)
at next (E:\test\node_modules\express\lib\router\route.js:137:13)
at Immediate._onImmediate (test\node_modules\multer\lib\make-middleware.js:53:37)
at processImmediate (internal/timers.js:463:21
当我输入带有 2 个字符而不是 3 个字符的标题时,我从验证器收到的错误
TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string or an instance of Buffer or URL. Received undefined
【问题讨论】:
-
您上次的编辑似乎不小心从您的问题中删除了大部分信息。它需要提供尽可能多的内容,以便尽可能容易和清楚地回答。我为你解开了那个编辑。请再次尝试预期的“较小”编辑。
标签: node.js mongodb express upload multer