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

Angular14向ASP.NET6上传FormData报错:请求表单读取失败

解决FormData上传流读取错误的方案

1. 修复Angular服务的请求头问题

手动指定multipart/form-data的boundary会和浏览器自动生成的冲突,导致ASP.NET无法正确解析请求体。直接移除自定义的Content-Type头:

修改服务类代码:

postAdvertisement(formData: FormData): Observable<Advertisement> {
    // 移除手动设置的Content-Type,浏览器会自动处理边界符
    return this.http.post<Advertisement>(this.baseApiUrl + '/api/advertisements', formData);
}

2. 修正Angular组件中FormData的字段映射

当前FormData的字段名和API端模型不匹配,数组字段格式错误,导致模型绑定失败,同时间接引发流读取冲突。调整FormData构建逻辑:

修改组件的addAdvertisement方法:

addAdvertisement() {
    this.mapFormValuesToAdvModel();

    const formData = new FormData();
    formData.append('id', this.adv.id.toString());
    formData.append('name', this.adv.name);
    formData.append('price', this.adv.price.toString());
    formData.append('description', this.adv.description);

    // 正确映射Features数组,使用索引格式匹配API模型
    this.adv.features.forEach((feature, index) => {
        formData.append(`features[${index}].id`, feature.id.toString());
        formData.append(`features[${index}].name`, feature.name);
    });

    // 正确映射Images数组的文件字段,对应API模型的Contents属性
    this.files.forEach((file, index) => {
        formData.append(`images[${index}].Contents`, file, file.name);
        formData.append(`images[${index}].id`, '0');
    });

    this.advertisementService.postAdvertisement(formData)
        .subscribe(add => {
            console.log(add);
        });
}

3. 修正ASP.NET控制器的请求读取逻辑

控制器中同时使用[FromForm] AdvModel model和Request.Form.Files会导致请求流被两次读取,触发“Unexpected end of Stream”错误。直接从绑定后的模型中获取文件:

修改控制器代码:

[HttpPost]
[Consumes("multipart/form-data")]
public IActionResult PostAdv([FromForm] AdvModel model)
{
    try
    {
        Advertisement entity = new Advertisement();
        entity.Id = model.Id;
        entity.Name = model.Name;
        entity.Price = model.Price;
        entity.Description = model.Description;
        entity.Features = model.Features.ToEntityList();
                
        // 直接从模型的Images集合中取文件,避免重复读取请求流
        foreach (var imageModel in model.Images)
        {
            if (imageModel.Contents != null && imageModel.Contents.Length > 0)
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    imageModel.Contents.CopyTo(ms);
                    entity.Images.Add(new Image { Contents = ms.ToArray() });
                }
            }
        }
        
        new AdvHandler().PostAdv(entity);
        return Created(Request.Path, entity.ToModel());
    }
    catch (Exception ex)
    {
        return StatusCode(500, ex.Message); // 返回错误信息而非完整异常对象
    }
}

4. 确保AdvModel定义正确

确认API端的AdvModel包含对应集合属性,保证模型绑定能正确解析:

public class AdvModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Description { get; set; }
    public List<FeatureModel> Features { get; set; }
    public List<ImageModel> Images { get; set; }
}

public class FeatureModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

关键原因总结

  • Angular端手动设置Content-Type导致边界符不匹配,ASP.NET无法解析请求体。
  • 控制器重复读取请求流(模型绑定一次,Request.Form.Files一次),导致流提前耗尽。
  • FormData字段名与API模型字段不匹配,模型绑定失败后触发后续流读取错误。

内容的提问来源于stack exchange,提问作者Junior Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 05:05:44