26

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

抱歉有这么多问题,我是网络开发的新手:P

干杯。

4

3 回答 3

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

    response.AppendHeader("Content-Length", new FileInfo(path).Length.ToString());
    
  4. 我推荐4K;我的建议没有任何坚实的基础。
  5. 这种方法是最好的方法。通过在循环内部调用Flush,您可以立即通过线路发送响应,而无需任何缓冲。但是,为了提高性能,您可以使用 GZIP 压缩。
于 2010-04-02T21:48:19.367 回答
2
  1. 是的,它正在缓冲。
  2. Flush 将缓存的内容推送到浏览器。如果从不推送,则不会出现保存对话框。
  3. 如果没有看到您正在使用的确切文件/URL/流,很难分辨。
  4. 我认为这些因素取决于你的页面有多慢,真的。您将在 4k 上获得更好的性能。也许,较低的值会更好地适应较慢的连接。
  5. 参见#1 和 2。
于 2010-04-02T21:42:36.430 回答
2

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

我相信您可以通过将响应对象上的缓冲属性更改为 false 来更改缓冲。好久没做,所以不记得是什么了。

于 2010-04-02T21:47:47.690 回答