C#通过HTTPS下载FTP服务器文件时大文件加载卡顿如何解决?
问题根因
你当前的实现逻辑是先将目标文件全量读取到服务端内存的字节数组中,直到整个文件加载完成才会向客户端返回响应,这就是大文件下载时浏览器长时间处于加载状态、迟迟不弹出保存窗口的直接原因。这种实现除了用户体验差,还会额外占用大量服务端内存,大文件场景下很容易触发内存溢出、请求超时问题。
修复方案
删除全量读取文件到字节数组的逻辑,直接通过文件流返回结果,ASP.NET会自动完成流式分段传输:响应头会第一时间返回给浏览器,浏览器立刻弹出文件保存窗口,同时服务端会边读取文件边向客户端传输数据,不需要等待整个文件加载完成。
优化后的代码如下:
public ActionResult Download(string filePath) { string fileName = "file.csv.gz"; string fileFullPath = @"\\myserver-ftp\f$\content\file.csv.gz"; // 以只读方式打开文件流,不提前加载全量内容到内存 FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read, FileShare.Read); // 直接传入流对象返回File结果,框架会自动处理流式传输 return File(fs, "application/gzip", fileName); }
你之前写的全量读文件的GetFile方法可以直接删掉,不需要再用。
可选优化项
- 如果需要浏览器展示精确的下载进度,可以在返回结果前手动添加
Content-Length响应头:
public ActionResult Download(string filePath) { string fileName = "file.csv.gz"; string fileFullPath = @"\\myserver-ftp\f$\content\file.csv.gz"; FileInfo fileInfo = new FileInfo(fileFullPath); FileStream fs = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read, FileShare.Read); // 写入内容长度头,浏览器可准确计算剩余下载时间、展示进度 Response.AppendHeader("Content-Length", fileInfo.Length.ToString()); return File(fs, "application/gzip", fileName); }
- 不要给返回的FileStream手动套
using语句,框架会在请求处理完成后自动释放流,套using反而会导致流提前释放,下载报错。 - 大文件传输场景下建议设置合适的流读取缓冲区大小,一般64KB(65536字节)是比较通用的配置,平衡内存占用和传输效率。
- 如果需要支持断点续传,ASP.NET Core 2.1及以上版本的FileResult默认已经支持Range请求处理,不需要额外编码;如果是ASP.NET MVC 5及更早版本,只需要简单处理请求中的Range头、返回206状态码即可实现。
内容的提问来源于stack exchange,提问作者Kiran B Chitari
相关产品推荐
相关产品推荐

