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

多附件上传遇System.ObjectDisposedException异常求助

多附件上传时抛出ObjectDisposedException异常问题

我编写了用于上传用户所有附件的代码(如下),单附件上传时正常,但多附件上传时第二次迭代会抛出异常,手动释放文件流、拆分单文件调用函数都无法解决。

上传代码

private async Task<List<AttchmentsMetaData>> UploadAttachments(IEnumerable<IFormFile> Attachments, string TaskTitle)
{
    // 1. 配置存储位置和路径生成
     string uploadPath = Path.Combine(_hostingEnvironment.ContentRootPath, "attachments",$"{TaskTitle}" );
    
    List<AttchmentsMetaData> metaData = [];
    // 2. 处理并存储每个上传文件
    Directory.CreateDirectory(uploadPath);
    foreach (IFormFile attach in Attachments)
    {
        string uniqueFileName = attach.FileName;
        string fullPath = Path.Combine(uploadPath, uniqueFileName);

        using (FileStream stream =  new FileStream(fullPath, FileMode.Create))
        {
            await attach.CopyToAsync(stream);
        }
        metaData.Add( new AttchmentsMetaData {id = Guid.NewGuid().ToString(), OriginalFileName = attach.FileName, ContentType = attach.ContentType, FileSize = attach.Length });
    }
    return (metaData);
}

异常信息

System.ObjectDisposedException: 'Cannot access a disposed object. Object name: 'System.String'.'

补充调试信息

  • 线程0x3838已退出,代码为0 (0x0)。
  • 在System.Private.CoreLib.dll中引发了'System.ObjectDisposedException'异常
  • 在System.Private.CoreLib.dll中引发了'System.ObjectDisposedException'异常
  • System.Private.CoreLib.dll中发生了类型为'System.ObjectDisposedException'的异常,但未在用户代码中处理
  • 无法访问已释放的对象。
  • 对象名: 'System.String'。
  • 调用栈:
    at Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.set_Position(Int64 value)
    at Microsoft.AspNetCore.Http.FormFile.OpenReadStream()
    at Microsoft.AspNetCore.Http.FormFile.CopyToAsync(Stream target, CancellationToken cancellationToken)
    at ticketing_system_Dev_Nxt_level.Services.TaskService.UploadAttachments(IEnumerable`1 Attachments, String TaskTitle) in D:\ASP.NET\ticketing-system-Dev-Nxt-level\Services\TaskService.cs:line 334
    

问题原因及解决方法

1. 解决IEnumerable延迟执行问题

传入的IEnumerable<IFormFile>通常是延迟加载的(比如直接从Request.Form.Files获取),第一次迭代后部分内部资源被释放,第二次访问时触发异常。只需提前将集合转为List,加载所有文件到内存:

private async Task<List<AttchmentsMetaData>> UploadAttachments(IEnumerable<IFormFile> Attachments, string TaskTitle)
{
    string uploadPath = Path.Combine(_hostingEnvironment.ContentRootPath, "attachments",$"{TaskTitle}" );
    List<AttchmentsMetaData> metaData = [];
    Directory.CreateDirectory(uploadPath);
    
    // 关键:先转为List避免延迟执行导致的资源释放问题
    var attachmentList = Attachments.ToList();
    foreach (IFormFile attach in attachmentList)
    {
        // 生成唯一文件名避免重名覆盖
        string uniqueFileName = $"{Guid.NewGuid()}_{Path.GetFileName(attach.FileName)}";
        string fullPath = Path.Combine(uploadPath, uniqueFileName);

        using (FileStream stream =  new FileStream(fullPath, FileMode.Create))
        {
            await attach.CopyToAsync(stream);
        }
        metaData.Add( new AttchmentsMetaData {id = Guid.NewGuid().ToString(), OriginalFileName = attach.FileName, ContentType = attach.ContentType, FileSize = attach.Length });
    }
    return metaData;
}

2. 修复文件名重复问题

原代码直接使用上传文件名存储,多文件重名时会覆盖旧文件,也可能引发流操作冲突。通过添加GUID前缀生成唯一文件名,确保文件存储不冲突。

3. 确认请求上下文未提前释放

检查调用UploadAttachments的代码,确保在控制器或请求处理流程中使用await异步调用,避免在请求上下文已被销毁后执行文件上传操作。

内容的提问来源于stack exchange,提问作者Mohamed Almuetaz Atif Altayeb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:08:18