首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Response.TransmitFile中使用Response.Filter

在Response.TransmitFile中使用Response.Filter
EN

Stack Overflow用户
提问于 2010-08-10 09:51:13
回答 2查看 1.2K关注 0票数 0

我使用Response.Filter是为了根据HTTP请求头Accept-Encoding实现流压缩

这里有一些重要的东西:

代码语言:javascript
复制
        if (AcceptEncoding.Contains("deflate") || AcceptEncoding == "*")
        {
             HttpApp.Response.Filter = new DeflateStream(PreviousOutputStream, CompressionMode.Compress);
             HttpApp.Response.AppendHeader("Content-Encoding", "deflate");
        }

大体上,这是预期的工作。但是,我遇到了这样一种情况:我在MVC控制器上使用ActionResult向用户代理提供文件:

代码语言:javascript
复制
        Response.Clear();
        Response.Headers["Content-Type"] = contentType;
        Response.Headers["Content-Length"] = contentLength;

        if (Request.QueryString["dl"] == "1")
        {
            Response.Headers["Content-Disposition"] = "attachment; filename=" + fileInfo.Name;
        }

        Response.Flush();
        Response.TransmitFile(fileInfo.FullName);

更准确地说,动作方法在Response.TransmitFile()调用之后返回new EmptyResult()。这在没有Response.Filter修改的情况下完全按照预期工作。

在这种情况下,响应实体到达用户代理时会变得混乱和难以理解。FireFox的海报插件显示了返回的空实体或杂乱的实体。

EN

回答 2

Stack Overflow用户

发布于 2010-11-05 09:11:31

如果你可以帮助它,一定要寻找替代方案,因为在ASP.NET中手动进行压缩并不有趣。但是,如果你像我一样头脑冷静,我向你提出以下几点。

首先:不要使用.NET内置的压缩流类。它们有buggy,可以随机截断数据流末尾的字节。我一直在使用DotNetZip,效果很好:http://dotnetzip.codeplex.com/

现在,还有一些注意事项:

  • Response.TransmitFile()不适用于响应过滤filtering.
  • Response.BinaryWrite()不适用于响应过滤,因此您不能循环遍历文件内容并将其写出way.
  • Response.OutputStream不适用于响应过滤,因此您不能循环遍历文件内容并以这种方式将其写出,either.
  • Response.WriteFile()确实适用于响应过滤,但它会将整个文件加载到内存中,并将其保留在内存中,直到客户端关闭连接为止。这对大文件不起作用。

  • ,让事情变得更有趣:如果你将Response.BufferOutput设置为false,响应过滤就会停止工作。(我花了几个小时才弄明白)

显然,围绕响应过滤和写入输出流有很多不同的问题。使用Reflector和大量的实验,这是我到目前为止找到的最好的(“最佳”是在各种场景下正确工作)的解决方案:

  1. 编写一个扩展编码的类,并将其命名为BinaryEncoding。实现所有的方法,以便它们正确地复制字符和字节,当然也要进行必要的类型转换。
  2. 将Response.ContentEncoding设置为BinaryEncoding的一个实例(您可以非常成功地使用单例模式)。
  3. 使用FileStream.
  4. Create a new StreamReader(fileStream, new BinaryEncoding(), false)打开您的文件。这个"false“参数非常重要,它会阻止charI've found that 32KB is a good size.

的StreamReader获取字节顺序标记并覆盖缓冲区

然后,在一个循环中:

代码语言:javascript
复制
int n = StreamReader.Read(buffer, 0, buffer.Length);
Response.Write(buffer, 0, n);
Response.Flush();

直到n为0。

注意:此方法会导致相当高的CPU使用率。在100兆局域网上,单个客户端以10MB/秒的速度下载时,一个核心上的CPU使用率约为40-50%。我希望我能找到更好的方法..。如果我有Reflector Pro,我也许能找到一个。

票数 1
EN

Stack Overflow用户

发布于 2010-08-12 02:37:23

如果您使用的是IIS7或IIS7.5,我建议您使用HTTP Compression模块,而不是使用自己的模块。这可能有助于解决这个问题。

http://technet.microsoft.com/en-us/library/cc771003(WS.10).aspx

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3445479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档