Angular向Node.js上传文件时文件数据为null的问题求助
问题:Node.js后端接收Angular上传文件时始终返回null
我正在开发Node.js后端与Angular前端的项目,前端发送POST请求后,后端可正常接收普通数据,但上传的文件数据始终显示为null。
相关截图:

后端代码(Node.js + multer)
const imageUpload = multer({ storage: multer.diskStorage({ destination: function (req, file, cb) { console.log("asd"); cb(null, "Attachments/"); }, filename: function (req, file, cb) { cb(null, new Date().valueOf() + "_" + file.originalname); }, }), limits: { fileSize: 10000000 }, fileFilter: function (req, file, cb) { if ( !file.originalname.match( /\.(jpg|JPG|webp|jpeg|JPEG|png|PNG|gif|GIF|pdf|PDF|docx|doc)$/ ) ) { req.fileValidationError = "Only Image, PDF and Word files are allowed!"; return cb(null, false); } else { req.fileValidationError = ""; } cb(null, true); }, }); // Add Property Details app.post('/addproperty', imageUpload.single("image"), (req, res) => { console.log("vicky", req.body.body.file); if (req.fileValidationError != "") { throw req.fileValidationError; } console.log(req.body.body) req.body.body = req.body; let qrr = 'INSERT INTO listproperty (Type, plotNo, location, sqft, sellType, facing, price, BedRoom, BAthRoom, Parking, date, Description, src)VALUES("'+req.body.Type+'","'+req.body.plotNo+'","'+req.body.location+'","'+req.body.sqft+'","'+req.body.sellType+'","'+req.body.facing+'", "'+req.body.price+'","'+req.body.BedRoom+'","'+req.body.BAthRoom+'","'+req.body.Parking+'","'+req.body.date+'","'+req.body.Description+'","'+req.body.src+'");' db.query(qrr, (err1, res1) => { if(err1)console.log(err1); else { res.send({ message: 'Data inserted', body:res1 }) } }) });
前端代码(Angular)
newProperty : any = new FormGroup({ Type: new FormControl([Validators.required]), sellType: new FormControl([Validators.required]), facing: new FormControl([Validators.required]), src: new FormControl(''), plotNo: new FormControl('', Validators.required), location: new FormControl('', Validators.required), price: new FormControl(Validators.required), sqft: new FormControl(Validators.required), BedRoom: new FormControl(Validators.required), BAthRoom: new FormControl(Validators.required), Parking: new FormControl(Validators.required), Description: new FormControl('', Validators.required), date: new FormControl([Validators.required]), }); // On file Select onChange(event: any) { this.newProperty.value.src = event.target.files; //console.log(event); // this.file = event.target.files[0]; } ngOnInit(): void { this.getPropertyType() this.sellType = this.data.getSellType(); let x = this.route.snapshot.paramMap.get('property') // if (x) { // var d=this.data.getSingleData(x) // console.log(d); // setTimeout(() => { // this.newProperty.patchValue(d) // // this.newProperty.setControl('src') // }, 1000); // } } getPropertyType() { console.log("res", this.sql.getPlotType()); this.sql.getPlotType().subscribe((res)=>{ console.log(res); for (let i = 0; i < res.length; i++) { this.plotType.push( res[i].propertyType); } // this.plotType =res }); } addNew() { if (this.newProperty.invalid) { alert('fill all details'); return; } var data = []; //JSON.parse(this.newProperty.value) this.sql.addplotdata(this.newProperty.value).subscribe((res)=>{ console.log(res); for (let i = 0; i < res.length; i++) { data.push( res); } console.log("data"); // this.plotType =res }); console.log(this.newProperty.value); // this.data.addData(this.newProperty.value); //this.newProperty.reset(); this.router.navigate(['add-property']); } addplotdata(value: any): Observable<any> { return this.http.post(this.addPropUrl, {value, "image" :value.src}); } // Backend.ts
问题原因及修复方案
核心问题
- 前端请求格式错误:文件上传必须使用
FormData格式,你当前用HttpClient.post发送JSON数据,multer无法从JSON中解析文件。 - 文件赋值方式错误:直接修改
this.newProperty.value.src不会触发表单控件的更新,且你赋值的是FileList而非单个File对象。 - 后端参数读取错误:multer处理单文件上传后,文件数据存储在
req.file中,而非req.body,你当前代码错误地从req.body.body.file读取。 - SQL注入风险:原SQL语句直接拼接字符串,存在严重安全隐患。
修复步骤
前端修改
- 修正文件选择事件:
onChange(event: any) { const file = event.target.files[0]; // 取单个文件,对应后端single上传 this.newProperty.patchValue({ src: file }); this.newProperty.get('src')?.markAsDirty(); // 手动标记控件为脏 }
- 用FormData发送请求:
addplotdata(formValue: any): Observable<any> { const formData = new FormData(); // 追加普通表单字段 Object.keys(formValue).forEach(key => { if (key !== 'src' && formValue[key]) { formData.append(key, formValue[key]); } }); // 追加文件,字段名与后端multer.single("image")一致 if (formValue.src) { formData.append('image', formValue.src); } return this.http.post(this.addPropUrl, formData); }
- 修正表单控件定义:
src: new FormControl(null) // 文件控件无需初始字符串值
后端修改
- 正确读取文件和表单数据:
app.post('/addproperty', imageUpload.single("image"), (req, res) => { if (req.fileValidationError) { return res.status(400).send({ error: req.fileValidationError }); } console.log('上传文件:', req.file); console.log('表单数据:', req.body); // 使用参数化查询避免SQL注入 const qrr = `INSERT INTO listproperty (Type, plotNo, location, sqft, sellType, facing, price, BedRoom, BAthRoom, Parking, date, Description, src) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; const values = [ req.body.Type, req.body.plotNo, req.body.location, req.body.sqft, req.body.sellType, req.body.facing, req.body.price, req.body.BedRoom, req.body.BAthRoom, req.body.Parking, req.body.date, req.body.Description, req.file ? req.file.filename : '' // 存储文件名,根据需求调整为路径或其他 ]; db.query(qrr, values, (err1, res1) => { if (err1) { console.error(err1); return res.status(500).send({ error: '数据插入失败' }); } res.send({ message: 'Data inserted', body: res1 }) }) });
内容的提问来源于stack exchange,提问作者romil_stage
相关产品推荐
相关产品推荐

