关于在ASP.NET响应流上编写的一些问题

时间:2010-04-02 21:36:32

标签: c# .net asp.net stream httpresponse

我正在使用ASP.NET HttpHandler进行测试,以便直接在响应流上下载文件,我不太确定我这样做的方式。这是一个示例方法,将来文件可以存储在数据库中的BLOB中:

        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()”行,当我用浏览器打开网址时,...我看到网络服务器如何推送数据但是“保存文件”对话框没有出现, (或者至少不是以合理的时间方式)为什么?
  3. 当我用WebRequest对象打开url时,我看到HttpResponse.ContentLength为“-1”,虽然我可以读取流并获取文件。 -1是什么意思?什么时候HttpResponse.ContentLength会显示响应的长度?例如,我有一个方法,用deflate作为二进制流检索一个大的xml,但在那种情况下...当我用WebRequest访问它时,在HttpResponse中我实际上可以看到ContentLength的流长度,为什么?
  4. 我用作缓冲区的Byte []数组的最佳长度是什么,以便在Web服务器中实现最佳性能?我读过这是介于4K和8K之间......但是我应该考虑哪些因素做出正确的决定。
  5. 这种方法是否会破坏IIS或客户端内存的使用?还是它实际上正确地缓冲了转移?
  6. 很抱歉这么多问题,我在网络开发方面很陌生:P

    干杯。

3 个答案:

答案 0 :(得分:17)

  1. 是;这很正常。
  2. 如果您从未刷新,则在服务器完成之前,浏览器不会得到任何响应(甚至不是Content-Disposition标头)。因此,它不知道显示文件对话框。
  3. 如果整个响应被缓冲(如果你从不刷新)或者你自己设置,Content-Length标头只会被设置。在这种情况下,您可以并且应该自己设置它;写

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

对于#3,您需要在http响应中设置content-length标头。其中许多值来自http标头。

我相信您可以通过将响应对象上的缓冲属性更改为false来更改缓冲区。有一段时间没有这样做,所以我不记得它可能是什么。