我是 multer npm 包的新手。我构建了一个带有几个文本输入字段和文件上传字段的表单。当我输入所有字段并提交时,数据被保存并上传文件,一切正常。但是没有上传文件直接点击提交就报这个错:
类型错误:无法读取未定义的属性(读取“文件名”)
注意:我正在使用 React.js 和 Node.js mongoDB
表格
<div className={`container ${addEventModule.addEventContainer}`}>
<form onSubmit={this.addEventHandler} encType="multipart/form-data">
<div className={addEventModule.addEventForm}>
<div className={`text-center ${addEventModule.title}`}>
<h3 style={{ color: '#2557A7'}}>Add Event</h3>
</div>
<hr />
<div className="text-center text-danger" style={this.state.others.errormessage ? {visibility: 'visible'} : {visibility: 'hidden'} }>
<span>{this.state.others.errormessage}</span>
</div>
<div className={addEventModule.addEventBody}>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<Input type="text" label="Event Name" name="event_name" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_name.value} />
</div>
<div className="col-md-12">
<span className="text-danger">{this.state.inputs.event_name.error === 1 ? this.state.inputs.event_name.errormessage : ''}</span>
</div>
</div>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<Textarea type="text" label="Event Description" name="event_description" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_description.value} rows="5" />
</div>
<div className="col-md-12">
<span className="text-danger">{this.state.inputs.event_description.error === 1 ? this.state.inputs.event_description.errormessage : ''}</span>
</div>
</div>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<Input type="date" label="Event Date" name="event_date" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_date.value} />
</div>
<div className="col-md-12">
<span className="text-danger">{this.state.inputs.event_date.error === 1 ? this.state.inputs.event_date.errormessage : ''}</span>
</div>
</div>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<Input type="file" label="Event Image" name="event_image" onchange={ (e) => this.inputChangeHandler(e) } />
</div>
<div className="col-md-12">
<span className="text-danger">{this.state.inputs.event_image.error === 1 ? this.state.inputs.event_image.errormessage : ''}</span>
</div>
</div>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<Select label="Event Category" name="event_category" onchange={ (e) => this.inputChangeHandler(e) } value={this.state.inputs.event_category.value} />
</div>
<div className="col-md-12">
<span className="text-danger">{this.state.inputs.event_category.error === 1 ? this.state.inputs.event_category.errormessage : ''}</span>
</div>
</div>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<div className="form-group">
<label className="form-label">Event Enabled</label>
<Radio type="radio" name="event_enabled" onchange={ (e) => this.inputChangeHandler(e) } value="Yes" labelValue="Yes" />
<Radio type="radio" name="event_enabled" onchange={ (e) => this.inputChangeHandler(e) } value="No" labelValue="No" />
</div>
</div>
<div className="col-md-12">
<span className="text-danger">{this.state.inputs.event_enabled.error === 1 ? this.state.inputs.event_enabled.errormessage : ''}</span>
</div>
</div>
</div>
<div className={addEventModule.addEventFooter}>
<div className={`row ${addEventModule.marginBottom}`}>
<div className="col-md-12">
<Button type="submit">Add Event</Button>
</div>
</div>
</div>
</div>
</form>
</div>
onsubmit函数
addEventHandler = (e) => {
e.preventDefault();
const event_name = this.state.inputs.event_name.value;
const event_description = this.state.inputs.event_description.value;
const event_date = this.state.inputs.event_date.value;
const event_image = this.state.inputs.event_image.value;
const event_category = this.state.inputs.event_category.value;
const event_enabled = this.state.inputs.event_enabled.value;
const event_featured = 'No';
const formData = new FormData();
formData.append('event_name',event_name);
formData.append('event_description',event_description);
formData.append('event_date',event_date);
formData.append('event_image',event_image);
formData.append('event_category',event_category);
formData.append('event_enabled',event_enabled);
formData.append('event_featured',event_featured);
axios({
method: 'post',
url: 'http://localhost:4000/sports-event/add-event',
data: formData
}).then( response => {
if(response.data.code === 0){
alert(response.data.message);
const initialStateOthers = {
...initialEventState.others
}
initialStateOthers['submitRedirect'] = 1;
this.setState({ ...this.state, others: initialStateOthers });
}else if(response.data.code === 2){
let duplicateStateInputs = {
...this.state.inputs
}
const fieldValue = [this.state.inputs.event_name.value, this.state.inputs.event_description.value,this.state.inputs.event_date.value,this.state.inputs.event_image.value,this.state.inputs.event_category.value,this.state.inputs.event_enabled.value];
const fieldArray = [this.state.inputs.event_name.type, this.state.inputs.event_description.type,this.state.inputs.event_date.type,this.state.inputs.event_image.type,this.state.inputs.event_category.type,this.state.inputs.event_enabled.type];
for(let i = 0; i < fieldArray.length; i++){
if(response.data.field === fieldArray[i]){
duplicateStateInputs = empty_field_validation(duplicateStateInputs, fieldArray[i], fieldValue[i], response.data.message);
}else{
duplicateStateInputs = empty_field_validation(duplicateStateInputs, fieldArray[i], fieldValue[i], '');
}
}
this.setState({ ...this.state, inputs: duplicateStateInputs});
}else{
const initialStateInputs = {
...initialEventState.inputs
}
const initialStateOthers = {
...initialEventState.others
}
initialStateInputs['event_name'].value = this.state.inputs.event_name.value;
initialStateOthers['errormessage'] = response.data.message;
this.setState({ ...this.state, inputs: initialStateInputs, others: initialStateOthers });
}
}).catch( err => {
console.log(err);
});
}
Node.js
const storage = multer.diskStorage({
destination: function(req, file, cb){
cb(null, path.join(__dirname,'../public/Images'));
},
filename: function(req, file, cb){
cb(null, Date.now() + file.originalname);
}
});
const fileFilter = function(req, file, cb){
if(file.mimetype === 'image/jpg' || file.mimetype === 'image/jpeg' || file.mimetype === 'image/png'){
cb(null, true);
}else{
cb(null, false);
}
}
const fileUpload = multer({
storage: storage,
fileFilter: fileFilter
}).single('event_image');
router.post('/sports-event/add-event', fileUpload, eventController.addEvent);
添加事件控制器
exports.addEvent = (req, res, next) => {
const event_name =req.body.event_name;
const event_description=req.body.event_description;
const event_date=req.body.event_date;
const event_image=req.file;
const imagePath = 'Images/' + req.file.filename;
const event_category=req.body.event_category;
const event_enabled=req.body.event_enabled;
const event_featured= req.body.event_featured;
// ------------------- Validations -----------------------------
if(Event.check_field_if_empty(event_name) == 1){
return res.json({
code: 2,
message: `Event Name is mandatory`,
field: 'event_name'
});
}else if(!Event.event_name_regex(event_name)){
return res.json({
code: 2,
message: `Event name must contain only capitals letters`,
field: `event_name`
})
}else if(Event.check_field_if_empty(event_description) === 1){
return res.json({
code: 2,
message: `Event Description is mandatory`,
field: 'event_description'
});
}else if(!Event.only_letters_numbers(event_description)){
return res.json({
code: 2,
message: `Event Description must contain only letters and numbers, no special characters`,
field: 'event_description'
});
}else if(Event.check_field_if_empty(event_date) === 1){
return res.json({
code: 2,
message: `Event Date is mandatory`,
field: 'event_date'
});
}else if(Event.check_field_if_empty(event_image) === 1){
return res.json({
code: 2,
message: `Event Image is mandatory`,
field: 'event_image'
});
}else if(Event.check_field_if_empty(event_category) === 1){
return res.json({
code: 2,
message: `Event Category is mandatory`,
field: 'event_category'
});
}else if(Event.check_field_if_empty(event_enabled) === 1){
return res.json({
code: 2,
message: `Event Enabled is mandatory`,
field: 'event_enabled'
});
}
Event.check_if_events_exists(event_name, event_category).then( response => {
if(response.length > 0){
res.json({
code: 1,
message: "This Events already exists"
});
}else{
Event.add_event(event_name, event_description, event_date, imagePath, event_category, event_enabled, event_featured).then( response => {
res.json({
code: 0,
message: "Event Added Successfully"
});
}).catch( err => {
return res.json({
code: 1,
message: `Error : ${err}`
});
});
}
}).catch( err => {
return res.json({
code: 1,
message: `Error : ${err}`
});
});
}
上述验证不起作用。
我也遇到了这个错误,但我的错误是通过在我的模型中将 path.dirname(process.main.filename) 更改为 path.dirname(process.mainModule.filename) 来修复的。虽然我用的是快递。