使用内存流下载大文件

bom*_*sen 5 c# ftp

我正在编写一个通用处理程序,用于从安全的 FTP 服务器下载相当大(400+ mb)的文件。我通过将响应流复制到 MemoryStream,然后二进制写入字节数组,让代码在小型测试图像上运行。

我的代码如下所示(DownloadFile.ashx):

// Set correct path
string path = ftpHelper.GetCompletePath();
path += "/" + loginId + "/" + folderName + "/" + fileName;

FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
request.UsePassive = false;
request.Credentials = new NetworkCredential(ftpHelper.Username, ftpHelper.Password);

byte[] fileBytes = null;

using (var response = (FtpWebResponse)request.GetResponse())
{
    using (Stream responseStream = response.GetResponseStream())
    {
        using (var memoryStream = new MemoryStream())
        {
            if (responseStream != null) responseStream.CopyTo(memoryStream);
            fileBytes = memoryStream.ToArray();
        }
    }
 }

if (fileBytes.Length > 0)
{
     context.Response.AppendHeader("Content-Length", fileBytes.Length.ToString());
     context.Response.BinaryWrite(fileBytes);
}

request.Abort();

context.ApplicationInstance.CompleteRequest();
Run Code Online (Sandbox Code Playgroud)

问题是:在一个具有 8GB 内存的实时网络服务器上(它目前使用了现有内存的 60%,因为它是一个相当大的网站!它可能需要内存升级;-))使 CopyTo() 和使用 MemoryStream 处理这么大的文件?

我知道我可以通过ftp://username:password@path.com将客户端上的下载链接直接设置到 FTP 服务器,但是 FTP 上的内容是受密码保护的,因为上面有一些敏感数据。

那么,内存流对于如此大的文件使用安全吗?如果没有:是否有其他我忽略的方法可以做到这一点?

提前致谢 :-)

Xen*_*ing 4

MemoryStream对于大文件来说是“安全”的。但是,您会将整个文件加载到内存中,并且它将保留在那里,直到垃圾收集确定回收该内存的好时机。

8GB RAM 对于“中等”负载生产服务器来说足够了。当然,这是客观的,但如果单个中低流量 WebApp 使用超过 8GB 的​​ RAM,则应该修改一些设计决策。

有两个选项可以避免将整个远程文件加载到内存中:

  1. 将其写入磁盘上的本地文件,并将该文件返回给 WebApp 客户端
  2. 直接对响应流进行分块写入

选项 2 可能类似于:

//...
using (Stream responseStream = response.GetResponseStream())
{
    Response.BufferOutput= false;   // to prevent buffering 
    byte[] buffer = new byte[1024]; 
    int bytesRead = 0; 
    while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)  
    { 
         Response.OutputStream.Write(buffer, 0, bytesRead); 
    }
}
//...
Run Code Online (Sandbox Code Playgroud)