我正在编写一个通用处理程序,用于从安全的 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 上的内容是受密码保护的,因为上面有一些敏感数据。
那么,内存流对于如此大的文件使用安全吗?如果没有:是否有其他我忽略的方法可以做到这一点?
提前致谢 :-)
MemoryStream对于大文件来说是“安全”的。但是,您会将整个文件加载到内存中,并且它将保留在那里,直到垃圾收集确定回收该内存的好时机。
8GB RAM 对于“中等”负载生产服务器来说足够了。当然,这是客观的,但如果单个中低流量 WebApp 使用超过 8GB 的 RAM,则应该修改一些设计决策。
有两个选项可以避免将整个远程文件加载到内存中:
选项 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)