HTTP响应过滤器无法第二次解码响应字节

我开发了一个IIS 7 HttpModule。 我的目标是检查特定标签的响应内容。 如果找到标签,则会记录一些内容。

为了实现我的目标,我开发了一个定制的ASP NET Response Filter。 此过滤器扩展了.NET Stream类。

过滤器在OnPreRequestHandlerExecute(Object source,EventArgs e)事件上注册。

HTTP模块已被正确注册。 过滤器正在工作。 问题是,当我刷新页面时,写入写入(byte []缓冲区,int偏移量,int count)方法会按预期方式调用,但是,在解码它们时,字节的内容是gobbledygook。

它让我感到困惑,因为第一次响应字节被正确解码,但是在第二次请求(即页面刷新)后,它们不是。 下面是过滤器设置的代码以及过滤器的写入方法的代码。 任何帮助将不胜感激,因为我已经花了3天时间,调试,研究谷歌,但仍然没有喜悦。

public void OnPreRequestHandlerExecute(Object source, EventArgs e)
{

    HttpResponse response = HttpContext.Current.Response;
    if (response.ContentType == "text/html")
    {
        response.ContentEncoding = Encoding.UTF8; //forcing encoding UTF8
        response.Charset = "charset=utf-8";
        Encoding encoding = response.ContentEncoding;
        string encodingName = encoding.EncodingName;
        response.Filter = new MyFilter(response.Filter, response.ContentEncoding);
    }
}

    public override void Write(byte[] buffer, int offset, int count)
    {
        string strBuffer = string.Empty;

        try
        {
            strBuffer = Encoding.UTF8.GetString(buffer);
        }
        catch (EncoderFallbackException ex)
        {
            log(ex.Message);
        }


        // buffer doesn't contain the HTML end tag so we keep storing the 
        //incoming chunck of data

        if (!strBuffer.Contains("</html>"))
        {
            log(strBuffer.ToString() );
            _responseHtml.Append(strBuffer);

        }
        //the strbuffer contains the HTLM end tag ; we wrap it up now
  else
        {
            _responseHtml.Append(strBuffer); //append last chunck of data
            string finalHtml = _responseHtml.ToString();


               byte[] bytesBuffer = Encoding.UTF8.GetBytes(finalHtml);
                outputStream.Write(bytesBuffer, 0, bytesBuffer.Length);
            }

        }

    }

这是我得到的,解码响应字节后,第二次调用html页面(即在浏览器上刷新)

? B 0 0 0 0 0 0 YW ?? / ????噩?? V. AK T:?JHY ?? XP,U I Y???? ?“ 0 ??? W |????{?] ?? _}!?w ^ ??? 0R M Y ?? I7E ???Ž?? 8K ?? 50 8 ???? -6 K -1 ^〜ķ?ú???? F·LE ????? S = I 10 GQY%22 O ???? <9X ??? BKuZg?一个??? 4? FQ ??? KJ?吨?? 8 ?????????? $é?é?,?

更新

第一个计时器,所以我不知道如何更新这个。 所以我正在把我所做的努力缩小/解决问题。

首先,仍然没有喜悦。 :-(

这就是我所做的:

  • 由于Write方法可以通过ASP NET多次调用,因此我将这些字节存储在一个集合中,将它们添加到集合中,每次Write方法被ASP NET调用时
  • p

    ublic override void Write(byte[] buffer, int offset, int count)
                    {
    
                            for (int i = 0; i < count; i++)
                            {
                                bytesList.Add(buffer[i]);
                            }
                            log("Write was called "+ "number of bytes: "+ bytesList.Count + " - " + count);
                    }
    
  • 在flush方法中,我调用一个方法来处理收集的所有字节:

    public override void Flush(){byte [] bytesContent = ProcessResponseContent(bytesList); outputStream.Write(bytesContent,0,bytesContent.Length); outputStream.Flush(); }

    public override void Write(byte [] buffer,int offset,int count){

            for (int i = 0; i < count; i++)
            {
                bytesList.Add(buffer[i]);
            }
            log("Write was called " + "number of bytes: " + bytesList.Count + " -" + count);
        }
    

    private byte [] ProcessResponseContent(List bytesList){

           byte[] bytesArray = bytesList.ToArray();
            string html = string.Empty;
            byte[] encodedBytes = null;
    
            try
            {
                FilterEncoder encoder = new FilterEncoder();
                html = encoder.DecodeBytes(bytesArray.Length, bytesArray);
                encodedBytes = encoder.EncodeString(html);
                log("after encoding - encodedBytes" + encodedBytes.Length);
                log("after encoding - bytesArray" + bytesArray.Length);
            }
            catch (Exception ex)
            {
                log("exception ocurred " + ex.Message);
    

    .... .....
    }

  • ProcessResponseContent是一种愚蠢的方法。 它只是将字节列表转换为字节数组; 这个字节数组被解码成一个字符串。 现在,我们不应该有任何问题,因为我们获得了在响应中发送的所有字节(bytesList(List)),

    由于代码的目的是将解码后的字符串登录到文件中,所以字节数组不会返回。

            log("after decoding  " + html);
    

    当我创建一个UTF8Encoding时,我正在捕获一个异常。 异常会被记录到文件中。

    第一次获取html页面时,内容会记录到文件中。

    当我刷新页面(Ctrl + F5)时会记录一个异常:

    “发生异常无法将索引0处的字节[8B]从指定的代码页转换为Unicode”

    请记住,我的html页面内容非常小。 所有响应内容都在一个块上处理。

    第一次访问页面时,接收到的字节数是2805.恰好在这些字节被解码为字符串之前。

    第二次调用页面(Ctrl + F5)时,收到的数字字节在被解码之前是1436。

    为什么响应的字节数较少,我不确定。 这可能会影响解码操作。

    我希望这一切都有意义,请让我知道如果有什么不明确的。 我一直在寻找这个代码很长一段时间。

    谢谢,


    很难判断这是否是所有问题,但是您忽略了Writeoffsetcount参数,而是假设整个缓冲区都是有效的:

    strBuffer = Encoding.UTF8.GetString(buffer);
    

    你还假设这将是一组完整的字符 - 它可能包含(比方说)三字节字符中的两个字节。 您需要使您的数据流成为有状态,并使用Encoding.UTF8创建的Encoding.UTF8 Encoder来维护调用之间部分写入字符的状态。

    还要注意,你假设你会在一次调用中获得整个</html> - 而你可以在一次调用中获得</ ,在下一次获得html> 。 有可能ASP.NET真的只会给你打一次电话,但你可能不应该认为是这种情况。

    链接地址: http://www.djcxy.com/p/43783.html

    上一篇: HTTP Response filter can't decode the response bytes the second time

    下一篇: Help reading JSON from HttpContext.InputStream