2010-04-02 65 views
23

我正在使用ASP.NET HttpHandler进行测试,以便下载直接在响应流上写入的文件,而且我对于执行此操作的方式并不确定。这是一个实例方法,在今后的文件可以存储在一个BLOB在数据库:有关在ASP.NET响应流上编写的一些问题

 public void GetFile(HttpResponse response) 
    { 
     String fileName = "example.iso"; 
     response.ClearHeaders(); 
     response.ClearContent(); 
     response.ContentType = "application/octet-stream"; 
     response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName); 
     using (FileStream fs = new FileStream(Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), fileName), FileMode.Open)) 
     { 
      Byte[] buffer = new Byte[4096]; 
      Int32 readed = 0; 

      while ((readed = fs.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       response.OutputStream.Write(buffer, 0, readed); 
       response.Flush(); 
      } 
     } 
    } 

但是,我不知道这是否是正确的或有更好的方法来做到这一点。 我的问题是:

  1. 当我打开与浏览器的网址,会出现“保存文件”对话框......但它似乎是在服务器启动已经将数据推入流之前,我点击“保存“,这是正常的吗?
  2. 如果我删除了“response.Flush()”这一行,当我用浏览器打开url时,...我看到web服务器如何推送数据但“保存文件”对话框没有出现, (或者至少不是以合理的时间方式)为什么?
  3. 当我用WebRequest对象打开url时,我发现HttpResponse.ContentLength是“-1”,尽管我可以读取流并获取文件。什么是-1的含义? HttpResponse.ContentLength何时显示响应的长度?例如,我有一个方法检索一个大的xml压缩作为二进制流,但在这种情况下...当我用WebRequest访问它时,在HttpResponse中我实际上可以看到ContentLength与流的长度,为什么?
  4. 什么是Byte []数组的最佳长度,我用它作为缓冲区以实现Web服务器的最佳性能?我读过的是4K和8K之间......但我应该考虑哪些因素才能做出正确的决定。
  5. 此方法是否会扩大IIS或客户端内存使用量?或者它实际上是否正确缓冲了传输?

对不起,这么多问题,我在网络的发展很新:P

干杯。

+1

你还应该看看这里的锅炉板HttpHandler实现(http://haacked.com/archive/2005/03/17/AnAbstractBoilerplateHttpHandler.aspx)和这里(http://www.hanselman.com /blog/PermaLink,guid,5c59d662-b250-4eb2-96e4-f274295bd52e.aspx)。 – R0MANARMY 2010-04-02 21:56:22

+0

您的学习方式值得赞赏。继续 。 – 2013-01-31 05:57:36

+0

这将工作: [http://stackoverflow.com/questions/3362849/outofmemoryexception-when-send-big-file-500mb-using-filestream-aspnet][1] [ 1]:http://stackoverflow.com/questions/3362849/outofmemoryexception-when-send-big-file-500mb-using-filestream-aspnet – 2014-09-16 11:54:26

回答

16
  1. 是的;这个是正常的。
  2. 如果你永远不会刷新,浏览器将不会收到任何回应,直到serever结束(甚至不包括Content-Disposition标头)。因此,它不知道显示文件对话框。
  3. Content-Length头只有在整个响应被缓冲(如果你永远不会刷新)或者你自己设置的时候才会被设置。在这种情况下,你可以并且应该自己设置;写

    response.AppendHeader("Content-Length", new FileInfo(path).Length.ToString()); 
    
  4. 我推荐4K;我对这项建议没有任何坚实的基础。
  5. 这种方法是最好的方法。通过在循环内调用Flush,您可以立即发送响应,而无需任何缓冲。但是,为了增加性能,您可以使用GZIP压缩。
+0

谢谢你,你清楚我的疑惑。我很高兴我加入了这个社区:D – vtortola 2010-04-02 23:00:12

2
  1. 是的,它是缓冲。
  2. 刷新将缓存的内容推送到浏览器。如果它从未被推动,你将不会得到一个保存对话框。
  3. 很难说没有看到您正在使用的确切文件/网址/流。
  4. 我认为这些因素取决于你的页面是多么迟钝,真的。你将有更好的表现4K。也许,较低的值会更好地适应较慢的连接。
  5. 见#1 & 2.
+0

谢谢你,你清除我所有的疑惑。我很高兴我加入了这个社区:D – vtortola 2010-04-02 22:58:44

2

对于#3你需要设置你的HTTP响应的Content-Length头。其中许多值来自http标头。

我相信你可以通过改变响应对象的缓冲属性为false来改变缓冲环。有一段时间没有做过,所以我不记得它会是什么。

+0

谢谢你,你清楚我所有的疑惑。我很高兴我加入了这个社区:D – vtortola 2010-04-02 22:59:30