ASP.NET Core Code First模式实现图片上传及Postman调用报错求助
问题排查与修复方案
报错核心原因
415不支持媒体类型错误由以下几个问题共同导致:
- 带
[ApiController]的控制器默认期望接收application/json格式的请求,而文件上传需要用multipart/form-data格式,你的POST接口参数没有添加[FromForm]特性显式声明接收表单格式,因此会拒绝form-data格式的请求 [Bind]属性遗漏了ImageFile字段,导致上传的文件无法绑定到模型- POST接口没有显式配置路由,按
/api/Image/Create访问会匹配不到接口 - 缺少文件夹存在性校验,如果没提前在wwwroot下创建Image文件夹,保存文件时会额外抛出路径不存在报错
- 原有返回逻辑是适配MVC页面的重定向,对接前后端分离场景时前端无法接收正确的响应结果
修复后的控制器代码
// 显式指定路由,支持POST api/Image/Create [HttpPost("Create")] // 声明接收Form表单格式的参数,Bind加上ImageFile字段 public async Task<IActionResult> Create([FromForm][Bind("ImageId,Title,ImageName,ImageFile")] ImageModel imageModel) { if (ModelState.IsValid) { // 增加文件非空校验,避免空引用报错 if (imageModel.ImageFile == null || imageModel.ImageFile.Length == 0) { ModelState.AddModelError("ImageFile", "请选择要上传的图片"); return BadRequest(ModelState); } // 保存图片到wwwroot/image string wwwRootPath = _hostEnvironment.WebRootPath; string fileName = Path.GetFileNameWithoutExtension(imageModel.ImageFile.FileName); string extension = Path.GetExtension(imageModel.ImageFile.FileName); imageModel.ImageName = fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension; // 自动创建不存在的文件夹 string imageDir = Path.Combine(wwwRootPath, "Image"); if (!Directory.Exists(imageDir)) { Directory.CreateDirectory(imageDir); } string path = Path.Combine(imageDir, fileName); using (var fileStream = new FileStream(path, FileMode.Create)) { await imageModel.ImageFile.CopyToAsync(fileStream); } // 插入数据库记录 _context.Add(imageModel); await _context.SaveChangesAsync(); // 返回JSON格式的成功结果适配前端调用 return Ok(new { imageModel.ImageId, imageModel.Title, imageModel.ImageName }); } return BadRequest(ModelState); }
Postman测试步骤
- 新建POST请求,地址填
https://你的后端地址/api/Image/Create - 切换到Body选项卡,选择
form-data格式 - 按字段填写参数:
Title:填写自定义的图片标题ImageFile:右侧类型下拉选择File,然后选中本地要上传的图片
- 不要手动设置Content-Type请求头,Postman会自动生成带boundary的
multipart/form-data请求头,手动设置反而会导致报错 - 点击发送即可收到上传成功的响应结果
Angular对接实现方案
1. 上传组件HTML代码(upload-image.component.html)
<div class="upload-container"> <input type="file" #fileInput accept="image/*" (change)="onFileSelected($event)" hidden> <button (click)="fileInput.click()">选择图片</button> <div *ngIf="selectedFile" class="file-info"> <p>选中文件:{{selectedFile.name}}</p> <input type="text" [(ngModel)]="title" placeholder="请输入图片标题"> <button (click)="uploadImage()" [disabled]="uploading"> {{uploading ? '上传中...' : '确认上传'}} </button> </div> <div *ngIf="uploadResult" class="result"> <p>上传成功!<a href="/Image/{{uploadResult.imageName}}" target="_blank">点击查看图片</a></p> </div> </div>
2. 组件TS代码(upload-image.component.ts)
需提前在AppModule中导入HttpClientModule、FormsModule:
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-upload-image', templateUrl: './upload-image.component.html', styleUrls: ['./upload-image.component.css'] }) export class UploadImageComponent { selectedFile: File | null = null; title = ''; uploading = false; uploadResult: any = null; // 替换为你的后端接口地址 private apiUrl = 'https://你的后端地址/api/Image/Create'; constructor(private http: HttpClient) {} onFileSelected(event: any): void { if (event.target.files.length > 0) { this.selectedFile = event.target.files[0]; } } uploadImage(): void { if (!this.selectedFile || !this.title.trim()) { alert('请选择图片并填写标题'); return; } this.uploading = true; // 使用FormData封装上传参数 const formData = new FormData(); formData.append('Title', this.title); formData.append('ImageFile', this.selectedFile, this.selectedFile.name); this.http.post(this.apiUrl, formData).subscribe({ next: (res) => { this.uploadResult = res; this.uploading = false; // 重置表单 this.selectedFile = null; this.title = ''; }, error: (err) => { console.error('上传失败', err); alert('上传失败,请检查参数后重试'); this.uploading = false; } }) } }
3. 配套后端配置
- 确保Program.cs中已经添加了静态文件中间件
app.UseStaticFiles();,这样wwwroot下的图片可以直接通过https://后端地址/Image/图片文件名访问 - 后端配置CORS跨域规则,允许Angular前端的域名访问接口,避免跨域报错
内容的提问来源于stack exchange,提问作者scorpion private
相关产品推荐
相关产品推荐

