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

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测试步骤

  1. 新建POST请求,地址填https://你的后端地址/api/Image/Create
  2. 切换到Body选项卡,选择form-data格式
  3. 按字段填写参数:
    • Title:填写自定义的图片标题
    • ImageFile:右侧类型下拉选择File,然后选中本地要上传的图片
  4. 不要手动设置Content-Type请求头,Postman会自动生成带boundary的multipart/form-data请求头,手动设置反而会导致报错
  5. 点击发送即可收到上传成功的响应结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:24:01