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

Blazor Server+ASP.NET Core多文件上传功能异常问题排查

问题:Blazor Server多文件上传异常排查与解决

问题背景

前后端分离项目,前端基于Blazor Server开发,后端为ASP.NET Core,文件上传功能出现异常:前端打印Check-3日志后触发请求发送错误,后端未接收到请求;多文件上传时还会出现文件ID不存在的错误。项目其他接口运行正常,已验证请求URL与后端端点匹配。


前端文件上传服务代码

public async Task<IEnumerable<FileMetaDataDto>> UploadFileAsync(IList<IBrowserFile> files, Guid projectId, Guid? commentId)
{
    using var content = new MultipartFormDataContent();
    
    foreach (var file in files)
    {
        var fileContent = new StreamContent(file.OpenReadStream());
        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "files",
            FileName = file.Name,
        };
        
        fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);

        content.Add(fileContent);
    }
    
    Console.WriteLine($"Check-3 {projectId}, Comment ID: {commentId}, Content: {content}");

    var response = await _httpClient.PostAsync($"api/Files/project/{projectId}/upload-multiple?commentId={commentId}", content);
    response.EnsureSuccessStatusCode();

    return await response.Content.ReadFromJsonAsync<IEnumerable<FileMetaDataDto>>();
}

后端ASP.NET Core控制器代码

[HttpPost("project/{projectId}/upload-multiple")]
public async Task<IActionResult> UploadMultiple(IEnumerable<IFormFile> files, Guid projectId, [FromQuery] Guid? commentId)
{
    Console.WriteLine("Check server side");
    var results = await _fileService.UploadMultipleFilesAsync(files, projectId, commentId);

    return Ok(results);
}

错误信息

  1. 单/多文件上传时,前端打印Check-3后报错:

An error occurred while sending the request.
后端未打印Check server side日志。

  1. 多文件上传时额外触发错误:

Error: There is no file with ID 1. The file list may have changed.
Error: There is no file with ID 1. The file list may have changed.
at Ze (https://localhost:55327/_framework/blazor.server.js:1:36968)
at Object.readFileData (https://localhost:55327/_framework/blazor.server.js:1:36894)
at https://localhost:55327/_framework/blazor.server.js:1:3244
at new Promise ()
at y.beginInvokeJSFromDotNet (https://localhost:55327/_framework/blazor.server.js:1:3201)
at Yt._invokeClientMethod (https://localhost:55327/_framework/blazor.server.js:1:60713)
at Yt._processIncomingData (https://localhost:55327/_framework/blazor.server.js:1:58188)
at Yt.connection.onreceive (https://localhost:55327/_framework/blazor.server.js:1:51829)
at s.onmessage (https://localhost:55327/_framework/blazor.server.js:1:79974)

后端文件服务多文件上传代码

public async Task<List<FileMetadataDto>> UploadMultipleFilesAsync(IEnumerable<IFormFile> files, Guid projectId, Guid? commentId)
{
    var responses = new List<FileMetadataDto>();

    foreach (var file in files)
    {
        FileMetadataDto response = await UploadFileAsync(file, projectId, commentId);
        
        responses.Add(response);
    }

    return responses;
}

解决方案

1. 修复文件ID不存在错误

Blazor Server中<InputFile>的文件对象绑定客户端状态,异步操作后复用IBrowserFile会导致客户端文件资源释放,触发ID不存在错误。修改前端代码,立即将文件流读取到内存流:

public async Task<IEnumerable<FileMetaDataDto>> UploadFileAsync(IList<IBrowserFile> files, Guid projectId, Guid? commentId)
{
    using var content = new MultipartFormDataContent();
    
    foreach (var file in files)
    {
        // 立即读取文件到内存流,避免客户端资源释放
        using var memoryStream = new MemoryStream();
        await file.OpenReadStream().CopyToAsync(memoryStream);
        memoryStream.Position = 0;
        
        var fileContent = new StreamContent(memoryStream);
        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
        {
            Name = "files",
            FileName = file.Name,
        };
        
        fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);

        content.Add(fileContent);
    }
    
    Console.WriteLine($"Check-3 {projectId}, Comment ID: {commentId}, Content: {content}");

    var response = await _httpClient.PostAsync($"api/Files/project/{projectId}/upload-multiple?commentId={commentId}", content);
    response.EnsureSuccessStatusCode();

    return await response.Content.ReadFromJsonAsync<IEnumerable<FileMetaDataDto>>();
}

2. 排查请求发送失败问题

若修改后仍无法发送请求,检查以下项:

  • 确认_httpClient的BaseAddress配置正确,跨域规则(若前后端域名不同)已配置。
  • 后端添加文件大小限制配置(在Program.cs中):
builder.Services.Configure<FormOptions>(options =>
{
    options.MultipartBodyLengthLimit = 10 * 1024 * 1024; // 按需调整大小,示例为10MB
});
  • 捕获详细异常信息,替换response.EnsureSuccessStatusCode()为:
try
{
    var response = await _httpClient.PostAsync($"api/Files/project/{projectId}/upload-multiple?commentId={commentId}", content);
    if (!response.IsSuccessStatusCode)
    {
        var errorMsg = await response.Content.ReadAsStringAsync();
        Console.WriteLine($"Request failed: {response.StatusCode}, Details: {errorMsg}");
        throw new HttpRequestException($"Upload failed: {errorMsg}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Request error: {ex.Message}, Inner: {ex.InnerException?.Message}");
    throw;
}

3. 确保后端参数绑定正常

给后端控制器的files参数添加[FromForm]标记,明确绑定来源:

public async Task<IActionResult> UploadMultiple([FromForm] IEnumerable<IFormFile> files, Guid projectId, [FromQuery] Guid? commentId)

内容的提问来源于stack exchange,提问作者Mr Dot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:44:53