使用Angular和Spring Boot将文件及其他数据存入数据库遇问题求助
问题排查:FormGroup + FormData 上传文件及数据失败
我尝试通过FormGroup和FormData将文件与描述数据存入数据库,但代码存在问题——FormData中仅能看到图片文件名和文件本身,描述数据没有被正确添加。以下是我的代码:
服务层代码
imageUploadForm = new FormGroup({description: new FormControl(null)}); formObj = this.imageUploadForm.value; data = JSON.stringify(this.formObj); public createImageFormData(productImage: ProductImage, imageFile: File): FormData { const formData = new FormData(); formData.append('data', this.data); formData.append('name', imageFile.name); formData.append('imageFile', imageFile); new Response(formData).text().then(console.log) // 仅能看到图片名和图片被添加 return formData; }
模板代码
<form #newImageForm="ngForm" (ngSubmit)="onAddNewImage(newImageForm)"> <div> <label>Description</label> <input name="description" id="description" class="form-control" placeholder="Enter description here" /> </div> <div class="input-group mb-2"> <div class="custom-file"> <input multiple type="file" accept="image/*" name="location" (change)="onImageUrlChange($event)" class="custom-file-input" /> <label class="custom-file-label" ><span [hidden]="!fileName">{{ fileName }}</span> </label> <img *ngFor='let url of images' [src]="url" height="150" width="200px" style="margin: 3px;"> <br/> </div> </div> <button mat-raised-button color="primary" type="submit">Save</button> </form>
错误原因分析
- 表单类型不匹配:服务层用的是响应式FormGroup,但模板用的是模板驱动表单(ngForm),输入框未与FormGroup绑定,导致
imageUploadForm.value始终是空对象,序列化后的data为"{}",自然无法在FormData中看到有效内容。 - 表单值初始化时机错误:
formObj和data在类初始化时就赋值,此时用户还未输入任何内容,永远只能拿到初始的null值,不会随用户输入更新。 - FormData调试方法错误:
new Response(formData).text()无法完整输出FormData的所有键值对,这种方式不适用于查看FormData内容。
修复方案
1. 统一使用响应式表单
修改模板,将其绑定到服务层的imageUploadForm:
<form [formGroup]="imageUploadForm" (ngSubmit)="onAddNewImage()"> <div> <label>Description</label> <input formControlName="description" id="description" class="form-control" placeholder="Enter description here" /> </div> <div class="input-group mb-2"> <div class="custom-file"> <input multiple type="file" accept="image/*" name="location" (change)="onImageUrlChange($event)" class="custom-file-input" /> <label class="custom-file-label" ><span [hidden]="!fileName">{{ fileName }}</span> </label> <img *ngFor='let url of images' [src]="url" height="150" width="200px" style="margin: 3px;"> <br/> </div> </div> <button mat-raised-button color="primary" type="submit">Save</button> </form>
2. 动态获取表单最新值
将表单值的获取逻辑移到createImageFormData方法内部,确保每次调用都拿到用户最新输入:
imageUploadForm = new FormGroup({description: new FormControl(null)}); public createImageFormData(productImage: ProductImage, imageFile: File): FormData { // 实时获取当前表单值并序列化 const formObj = this.imageUploadForm.value; const data = JSON.stringify(formObj); const formData = new FormData(); formData.append('data', data); formData.append('name', imageFile.name); formData.append('imageFile', imageFile); // 正确查看FormData内容的方式 for (const [key, value] of formData.entries()) { console.log(`${key}:`, value); } return formData; }
3. 确保模块导入响应式表单模块
在对应组件的模块中导入ReactiveFormsModule,使响应式表单生效:
import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ imports: [ // 其他模块 ReactiveFormsModule ] }) export class YourModule { }
内容的提问来源于stack exchange,提问作者James Mwaura
相关产品推荐
相关产品推荐

