You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular中通过mat-form-field上传文件并对接.NET Core Web API存数据库

基于Angular Material + .NET Core Web API 的mat-form-field图片上传实现方案

主流实现方案分为两种,适配不同业务场景

方案1:表单数据+图片合并为FormData统一提交(适用提交表单时同步传图的常规场景)

Angular端实现

  • 首先自定义mat-form-field的文件输入组件,原生mat-form-field不直接支持file类型输入,采用「隐藏原生文件输入+按钮触发」的方式适配:
<mat-form-field appearance="fill">
  <mat-label>上传证件照</mat-label>
  <input 
    type="file" 
    accept="image/jpeg,image/png" 
    (change)="handleFileSelect($event)" 
    #fileInput 
    hidden
  >
  <button mat-stroked-button type="button" (click)="fileInput.click()" >选择图片</button>
  <mat-hint *ngIf="selectedFile">已选文件:{{selectedFile.name}}</mat-hint>
  <mat-error *ngIf="fileCheckFailed">请上传不超过2MB的JPG/PNG格式图片</mat-error>
</mat-form-field>
  • 组件逻辑层处理文件校验和FormData构建:
// 组件内声明变量
selectedFile: File | null = null;
fileCheckFailed = false;
// 表单分组需提前定义,包含其他业务字段
formGroup = this.fb.group({
  userName: [''],
  phone: ['']
});

constructor(private fb: FormBuilder, private http: HttpClient) {}

handleFileSelect(event: Event) {
  const input = event.target as HTMLInputElement;
  if (!input.files?.length) return;
  const targetFile = input.files[0];
  // 前端前置校验文件格式、大小
  const allowedTypes = ['image/jpeg', 'image/png'];
  if (allowedTypes.includes(targetFile.type) && targetFile.size <= 2 * 1024 * 1024) {
    this.selectedFile = targetFile;
    this.fileCheckFailed = false;
  } else {
    this.selectedFile = null;
    this.fileCheckFailed = true;
  }
}

handleSubmit() {
  if (this.formGroup.invalid || !this.selectedFile) return;
  // 构建FormData对象,同时携带业务字段和文件
  const submitData = new FormData();
  Object.keys(this.formGroup.controls).forEach(key => {
    submitData.append(key, this.formGroup.get(key)?.value);
  });
  submitData.append('uploadImage', this.selectedFile, this.selectedFile.name);

  // 发送请求
  this.http.post('/api/form/submit', submitData).subscribe({
    next: () => alert('提交成功'),
    error: () => alert('提交失败,请重试')
  })
}

.NET Core Web API端实现

  • 定义接收参数的DTO类:
public class FormSubmitDto
{
    public string UserName { get; set; }
    public string Phone { get; set; }
    public IFormFile UploadImage { get; set; }
}
  • 控制器接口实现:
[ApiController]
[Route("api/[controller]")]
public class FormController : ControllerBase
{
    [HttpPost("submit")]
    public async Task<IActionResult> Submit([FromForm] FormSubmitDto dto)
    {
        // 1. 校验业务参数合法性
        if (!ModelState.IsValid) return BadRequest(ModelState);

        // 2. 存储业务字段到数据库逻辑
        // ... 此处省略数据库写入代码

        // 3. 存储图片文件,可根据需求存本地磁盘/OSS云存储
        if (dto.UploadImage != null && dto.UploadImage.Length > 0)
        {
            // 生成唯一文件名避免重复
            var fileName = $"{Guid.NewGuid()}{Path.GetExtension(dto.UploadImage.FileName)}";
            var savePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", fileName);
            
            // 写入文件
            using var stream = new FileStream(savePath, FileMode.Create);
            await dto.UploadImage.CopyToAsync(stream);

            // 4. 将文件存储路径写入对应的数据库字段即可
            // ... 此处省略数据库更新代码
        }

        return Ok("提交成功");
    }
}
  • 可选配置:如果需要调整上传大小限制,在Program.cs中添加配置:
builder.Services.Configure<Microsoft.AspNetCore.Http.Features.FormOptions>(opt =>
{
    // 单表单最大提交大小设为10MB,按需调整
    opt.MultipartBodyLengthLimit = 10 * 1024 * 1024;
});

方案2:图片预上传+提交表单时关联文件标识(适用大文件/需上传进度/预览后再提交的场景)

  • 核心逻辑:用户选择图片后立刻触发上传,后端返回文件的唯一存储标识/访问地址,提交表单时仅需要把该标识和其他业务字段作为JSON提交即可,不需要再传二进制文件
  • 优势:支持断点续传、上传进度展示、失败重传,表单提交响应速度快
  • 实现差异:仅需要把Angular端的文件上传逻辑移到handleFileSelect方法中单独调用,后端新增一个单独的文件上传接口返回文件标识即可,原有表单提交接口不需要改动,直接接收JSON参数即可

注意事项

  • 不要直接给type="file"的input添加matInput属性,会触发样式兼容问题,采用隐藏原生input+按钮触发的方式适配即可
  • 后端必须二次校验文件格式、内容,不能完全信任前端的校验结果,避免恶意文件上传
  • 多文件上传场景下,仅需要把Angular端的selectedFile改为数组循环append到FormData,后端对应属性改为List<IFormFile>即可

内容的提问来源于stack exchange,提问作者Ammar Muhi ud din

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 19:36:03