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

Angular 5分块上传大文件至ASP.NET报MIME多部分流异常

解决大文件分块上传时的"MIME multipart stream 意外结束"错误

我之前也碰到过一模一样的问题,结合你的代码来看,主要是前端FileAPI的配置逻辑和后端的分块处理方式不匹配导致的,咱们一步步来修复:

前端代码核心问题修正

你的前端代码里有两个关键错误,直接导致了MIME流解析失败:

  1. 错误地用FormData包装文件传给FileAPI:FileAPI的files字段应该直接传入原生文件对象,提前包装成FormData会打乱分块上传时的MIME结构,让后端无法正确识别每一块的边界。
  2. 注释了分块上传的核心配置:chunkSize和formData是分块上传必须开启的配置,注释后FileAPI会以普通上传模式发送请求,和你想要的分块逻辑完全不符。

修改后的前端代码:

FileAPI.upload({
  url: 'http://localhost:22166/api/lbx/upload',
  headers: {
    'authorization': `Bearer ${this._svc.getToken()}`
    // 不要手动设置Content-Disposition,FileAPI会自动生成符合规范的请求头
  },
  // 直接传入文件对象,无需FormData包装
  files: { file: this.fileToUpload },
  // 开启FormData模式,适配后端的multipart处理逻辑
  formData: true,
  // 设置分块大小,这里用1MB示例,可根据需求调整
  chunkSize: 1.0 * FileAPI.MB,
  progress: function (evt){
    console.log((evt.loaded / evt.total) * 100);
  },
  complete: function (err, xhr){
    if (err) {
      const message = JSON.parse(xhr.responseText).ExceptionMessage;
      parent.saving = false;
      parent.snack(message);
    } else {
      console.log('completed');
    }
  }
});

后端代码适配分块逻辑

后端默认的MultipartFormDataStreamProvider是为完整文件上传设计的,分块上传时每次请求只传递部分文件流,所以会触发"流不完整"的错误。需要调整代码来支持分块的接收与拼接:

[HttpPost]
[Route("lbx/upload")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
// 除非需要跨域携带Cookie,否则关闭SupportsCredentials,避免额外跨域问题
public async Task<IHttpActionResult> UploadLBXProject()
{
    try
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            const string errorMsg = "Request content is not MIME multipart content and is unsupported.";
            AppEventLog.Error(errorMsg);
            return StatusCode(HttpStatusCode.UnsupportedMediaType);
        }

        // 获取FileAPI自动传递的分块参数:文件唯一ID、当前块索引、总块数、文件名
        var queryParams = Request.GetQueryNameValuePairs();
        var fileId = queryParams.FirstOrDefault(p => p.Key == "fileId").Value;
        var chunkIndex = int.Parse(queryParams.FirstOrDefault(p => p.Key == "chunkIndex").Value);
        var totalChunks = int.Parse(queryParams.FirstOrDefault(p => p.Key == "totalChunks").Value);
        var fileName = queryParams.FirstOrDefault(p => p.Key == "fileName").Value;

        var root = HttpContext.Current.Server.MapPath("~/App_Data");
        var targetFilePath = Path.Combine(root, fileName);

        // 处理分块写入:第一块创建新文件,后续块追加写入
        using (var targetStream = new FileStream(targetFilePath, chunkIndex == 0 ? FileMode.Create : FileMode.Append))
        {
            var provider = new MultipartFormDataStreamProvider(root);
            await Request.Content.ReadAsMultipartAsync(provider);
            
            var chunkFile = provider.FileData.First();
            using (var chunkStream = new FileStream(chunkFile.LocalFileName, FileMode.Open))
            {
                await chunkStream.CopyToAsync(targetStream);
            }
            // 删除临时生成的分块文件
            File.Delete(chunkFile.LocalFileName);
        }

        // 如果是最后一块,返回上传完成的响应
        if (chunkIndex == totalChunks - 1)
        {
            // 这里可以添加文件校验、解压等后续逻辑
            return Ok(new { Message = "File uploaded successfully" });
        }
        else
        {
            return Ok(new { Message = "Chunk uploaded successfully" });
        }
    }
    catch (Exception ex)
    {
        AppEventLog.Error(ex.Message);
        return InternalServerError(ex);
    }
}

额外注意事项

  • 不要手动设置Content-Type:让FileAPI自动生成带正确边界的multipart请求头,否则后端会无法识别流的分割点。
  • 目录权限:确保后端App_Data目录有读写权限,否则会出现文件写入失败的隐性错误。
  • 分块参数校验:后端可以增加对chunkIndex、totalChunks等参数的合法性校验,避免非法请求干扰。

内容的提问来源于stack exchange,提问作者Luis Lavieri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:02:46