C# 使用memorystream下载大文件

C# 使用memorystream下载大文件,c#,ftp,C#,Ftp,我正在编写一个通用处理程序,用于从安全的FTP服务器下载相当大(400+mb)的文件。通过将响应流复制到MemoryStream,然后对字节数组进行二进制写入,我让代码在小测试图像上运行 我的代码如下(DownloadFile.ashx): 问题是:在一个有8gb内存的实时Web服务器上(由于它是一个相当大的网站,目前使用的内存约为现有内存的60%!它可能需要ram升级;-),制作CopyTo()并使用MemoryStream处理如此大的文件是否安全 我知道我可以通过直接将客户端上的下载链接设置

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

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

问题是:在一个有8gb内存的实时Web服务器上(由于它是一个相当大的网站,目前使用的内存约为现有内存的60%!它可能需要ram升级;-),制作CopyTo()并使用MemoryStream处理如此大的文件是否安全

我知道我可以通过直接将客户端上的下载链接设置为FTP服务器,但是FTP上的内容是有密码保护的,因为上面有一些敏感数据

那么,memorystream与如此大的文件一起使用安全吗?如果没有,还有没有其他我忽略的方法


提前感谢:-)

使用内存流应该可以。记住,您不需要一次写入整个文件,继续写入数据,直到返回所有数据,然后关闭响应


看一看这个问题,了解如何将天分块返回

MemoryStream
用于大型文件是“安全的”。但是,您将把整个文件加载到内存中,它将一直保留在内存中,直到垃圾收集确定是回收该内存的好时机

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

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

  • 将其写入磁盘上的本地文件,并将该文件发送回WebApp客户端
  • 直接对响应流执行分块写入
  • 选项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); 
        }
    }
    //...
    

    非常感谢你的快速响应,伊恩:-我也找到了这个:(页面中间的C示例),所以基本上我可以通过这样做来跳过内存流。我要试一试@bomortensen是的,通常是任何流,只需一次写入位,谢谢您的答案和代码示例!我复制了你的代码,它可以开箱即用——而且速度非常快!:-)使用我的CopyTo()memorystream逻辑,实际开始下载图像需要一秒钟左右的时间。我没想到它会“正常工作”,这是一个不错的奖励!我也会研究改变缓冲区的大小。您可以调整它以匹配ftp服务器的吞吐量;这可能会对操作的整体速度产生另一个影响。当我使用这个文件时,我用firefox以二进制模式打开了这个文件!如何确保开始下载?
    //...
    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); 
        }
    }
    //...
    
        void WriteFile(string path, string filename)
        {
            using (FileStream fs = File.OpenRead(path))
            {
                //response is HttpListenerContext.Response... 
                Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet;
                Response.AddHeader("Content-disposition", "attachment; filename=" + filename); 
                byte[] buffer = new byte[64 * 1024];
                int read; 
                while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                {
                    Response.OutputStream.Write(buffer, 0, read);
                    Response.OutputStream.Flush(); //seems to have no effect
                } 
                Response.OutputStream.Close();
            }
            File.Delete(path);
            Response.End();
        }