当前位置: 首页 > ai >正文

ASP.NET/IIS New StreamContent(context.Request.InputStream) 不会立即复制整个请求流的内容到内存

StreamContent 的工作原理与内存占用

New StreamContent(context.Request.InputStream) 不会立即复制整个请求流的内容到内存。这个操作只是创建一个包装器,将原始的请求流(context.Request.InputStream)封装在 StreamContent 对象中,用于后续的异步处理。

详细解释

  1. 延迟执行
    StreamContent 是一个延迟执行的对象,它不会立即读取或缓冲整个流。只有在调用 ReadAsMultipartAsync 等方法时,才会开始异步读取流内容。

  2. 流式处理
    ASP.NET 在处理 multipart 请求时,会逐块读取请求流,解析每个部分的头部和内容,而不是一次性将整个请求加载到内存。这意味着:

    • 对于大文件上传,内存占用主要取决于同时处理的块大小(通常是几 KB 到几十 KB),而不是整个文件大小。
    • 当你使用 MultipartFormDataStreamProvider 时,文件内容会直接写入磁盘,而不是保留在内存中。
  3. 内存占用场景

    • 普通表单字段:较小的表单数据可能会被缓冲到内存中。
    • 文件上传:如果使用 MultipartMemoryStreamProvider,整个文件会被加载到内存(不推荐用于大文件);而 MultipartFormDataStreamProvider 会将文件写入磁盘,内存占用仅为元数据和临时缓冲区。

验证内存占用的代码示例

以下代码演示了如何监控处理上传时的内存使用:

Public Async Function ProcessUploadAsync(context As HttpContext) As Task' 记录初始内存使用Dim initialMemory = GC.GetTotalMemory(forceFullCollection:=True)Console.WriteLine($"初始内存: {initialMemory / 1024 / 1024:F2} MB")Dim uploadPath = context.Server.MapPath("~/Uploads")Dim provider = New MultipartFormDataStreamProvider(uploadPath)Dim content = New StreamContent(context.Request.InputStream)content.Headers.ContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType)' 解析前的内存使用Dim beforeParseMemory = GC.GetTotalMemory(forceFullCollection:=True)Console.WriteLine($"解析前内存: {beforeParseMemory / 1024 / 1024:F2} MB")Console.WriteLine($"内存增长: {(beforeParseMemory - initialMemory) / 1024 / 1024:F2} MB")' 开始解析(流式处理)Await content.ReadAsMultipartAsync(provider)' 解析后的内存使用Dim afterParseMemory = GC.GetTotalMemory(forceFullCollection:=True)Console.WriteLine($"解析后内存: {afterParseMemory / 1024 / 1024:F2} MB")Console.WriteLine($"解析过程内存增长: {(afterParseMemory - beforeParseMemory) / 1024 / 1024:F2} MB")' 处理上传的文件For Each file In provider.FileDataConsole.WriteLine($"文件保存路径: {file.LocalFileName}")Nextcontext.Response.StatusCode = 200context.Response.Write("上传完成")
End Function

关键结论

  1. 内存高效设计
    ASP.NET 的 MultipartFormDataStreamProvider 设计为流式处理大文件,避免将整个文件加载到内存。只要你使用这个提供程序,内存占用就会被控制在合理范围内。

  2. 避免常见陷阱

    • 不要多次读取流:请求流通常是不可重置的,读取一次后指针会移到末尾。
    • 不要使用 ReadAsStringAsync 或 ReadAsByteArrayAsync:这些方法会将整个流加载到内存,适合小数据,不适合文件上传。
  3. 优化建议

    • 对于超大型文件(如 GB 级别),考虑使用云存储服务(如 Azure Blob、AWS S3)直接流式上传。
    • 结合 MaxRequestLength 和 executionTimeout 配置限制最大上传大小和超时时间。

通过正确使用流式处理和磁盘存储,你可以实现高效的文件上传处理,同时保持低内存占用。

http://www.xdnf.cn/news/6676.html

相关文章:

  • 什么是本地事务,什么是分布式事务
  • 【MATLAB例程】线性卡尔曼滤波的程序,三维状态量和观测量,较为简单,可用于理解多维KF,附代码下载链接
  • ESP32开发之freeRTOS的任务通知
  • OpenCV CUDA模块中矩阵操作------归一化与变换操作
  • window nvidia-smi命令 Failed to initialize NVML: Unknown Error
  • 【学习笔记】因果推理导论第1课
  • 3D一览通为山东融科MES系统补全车间看图能力
  • 车道线检测----CLRNet
  • Elasticsearch倒排索引核心原理面试题
  • 视频孪生智慧风电场解决方案
  • 【C++/Qt shared_ptr 与 线程池】合作使用案例
  • 模板分享:网络最小费用流
  • css:倒影倾斜效果
  • Jenkins 最佳实践
  • 从数据包到可靠性:UDP/TCP协议的工作原理分析
  • 【localstorage、sessionStorage和cookie】
  • python报错:typeerror:type object is not subcriptable问题原因及解决方案
  • socket通信中的accept函数
  • 【vue】封装接口,全局字典,表格表头及使用
  • 子查询对多层join优化记录
  • 汉诺塔超算堆栈结构编码和流程详细设计(附源代码)
  • 什么是有向图 无向图 求图的邻接矩阵 软考
  • 搭建游戏云服务器的配置要求包括哪些条件?
  • S32DS使用JLINK编译调试问题点记录
  • Nginx常用命令
  • 在24GB显存大小的GPU上运行27GB的Pytorch模型
  • 基于 Java Socket 的多线程网络聊天程序
  • 依赖倒转原则:Java 架构设计的核心准则
  • 【数据机构】2. 线性表之“链表”
  • 如何使用 Solana Yellowstone gRPC 重新连接和重放插槽