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

向ASP.NET Core API发送IFormFile文件遇400错误的解决及MultipartFile方案

问题分析与解决方案

400错误的直接原因

ASP.NET Core的IFormFile是专门用于绑定**multipart/form-data格式**请求中的文件字段的。你将文件转为Base64字符串放入JSON请求体后,API端的模型绑定系统无法将Base64字符串映射到IFormFile类型,导致请求验证失败,返回400 Bad Request。


方案一:Base64方式的修复(不推荐)

如果一定要用JSON+Base64的方式,需要修改API端的接收逻辑,放弃IFormFile,改用自定义DTO接收Base64内容:

客户端(Dio)代码

保持原JSON请求逻辑,将Base64字符串与其他业务数据封装成对象发送:

import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';

Future<void> uploadBase64() async {
  const apiUrl = "https://your-api-url/upload-base64";
  final dio = Dio();
  
  final file = File("path/to/file.jpg");
  final bytes = await file.readAsBytes();
  final base64Content = base64Encode(bytes);

  final requestData = {
    "fileName": "test.jpg",
    "description": "测试文件",
    "base64Content": base64Content
  };

  try {
    final response = await dio.post(apiUrl, data: requestData);
    print("上传成功:${response.data}");
  } on DioException catch (e) {
    print("上传失败:${e.message}");
  }
}

API端(ASP.NET Core)代码

定义DTO并手动解析Base64为文件:

public class Base64UploadDto
{
    public string FileName { get; set; }
    public string Description { get; set; }
    public string Base64Content { get; set; }
}

[HttpPost("upload-base64")]
public IActionResult UploadBase64([FromBody] Base64UploadDto dto)
{
    if (string.IsNullOrEmpty(dto.Base64Content))
        return BadRequest("文件内容为空");

    try {
        var fileBytes = Convert.FromBase64String(dto.Base64Content);
        // 示例:保存文件到本地
        var savePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", dto.FileName);
        Directory.CreateDirectory(Path.GetDirectoryName(savePath));
        System.IO.File.WriteAllBytes(savePath, fileBytes);
        
        return Ok(new { Message = "上传成功", SavePath = savePath });
    }
    catch (FormatException) {
        return BadRequest("Base64格式无效");
    }
}

注意:Base64会使文件体积增大约30%,大文件传输时性能差,容易触发请求体大小限制,仅适合小文件场景。


方案二:最优实现——MultipartFile(Dio)+ IFormFile(API端)

这是标准的文件上传方案,适配性强、传输效率高,完全匹配IFormFile的设计逻辑。

客户端(Dio)代码

使用FormData和MultipartFile构建multipart/form-data请求:

import 'dart:io';
import 'package:dio/dio.dart';

Future<void> uploadWithMultipart() async {
  const apiUrl = "https://your-api-url/upload";
  final dio = Dio();

  // 准备文件和业务数据
  final file = File("path/to/your/file.jpg");
  final formData = FormData.fromMap({
    "fileName": "test.jpg",
    "description": "这是测试文件",
    // 对应API端IFormFile的参数名,必须一致
    "file": await MultipartFile.fromFile(
      file.path,
      filename: file.path.split('/').last, // 指定文件名
      contentType: MediaType("image", "jpeg"), // 可选:指定MIME类型
    ),
  });

  try {
    final response = await dio.post(
      apiUrl,
      data: formData,
      // 可选:监听上传进度
      onSendProgress: (int sent, int total) {
        print("上传进度:${(sent / total * 100).toStringAsFixed(2)}%");
      },
    );
    print("上传成功:${response.data}");
  } on DioException catch (e) {
    print("上传失败:${e.message}");
  }
}

如果是内存中的文件(比如从网络下载或生成的字节流),可以用MultipartFile.fromBytes:

MultipartFile.fromBytes(
  fileBytes,
  filename: "test.jpg",
  contentType: MediaType("image", "jpeg"),
)

API端(ASP.NET Core)代码

直接用IFormFile接收文件,配合表单数据绑定:

// 可选:用DTO封装表单数据,更整洁
public class FileUploadFormDto
{
    public string FileName { get; set; }
    public string Description { get; set; }
    public IFormFile File { get; set; }
}

[HttpPost("upload")]
public async Task<IActionResult> UploadFile([FromForm] FileUploadFormDto dto)
{
    if (dto.File == null || dto.File.Length == 0)
        return BadRequest("未选择文件");

    // 示例:保存文件到wwwroot/uploads目录
    var uploadDir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads");
    if (!Directory.Exists(uploadDir))
        Directory.CreateDirectory(uploadDir);

    var savePath = Path.Combine(uploadDir, dto.FileName);
    using (var stream = new FileStream(savePath, FileMode.Create))
    {
        await dto.File.CopyToAsync(stream);
    }

    return Ok(new { Message = "文件上传成功", SavePath = savePath });
}

额外配置与注意事项

  1. API端大文件支持:默认ASP.NET Core限制multipart请求大小为1MB,上传大文件需在Program.cs中配置:
builder.Services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = 50 * 1024 * 1024; // 设置为50MB,按需调整
});
  1. Dio端超时配置:大文件上传需延长超时时间:
final dio = Dio(BaseOptions(
  connectTimeout: const Duration(minutes: 2),
  receiveTimeout: const Duration(minutes: 2),
));

内容的提问来源于stack exchange,提问作者Mohammad Alamoudi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 22:57:27