2

我创建了一个简单的 HttpModule 和响应流来重新格式化网页的呈现输出(参见下面的代码片段)。

在 HttpModule 中,我将 Response.Filter 设置为我的 PageStream:

m_Application.Context.Response.Filter = new PageStream(m_Application.Context);

在 PageStream 中,我覆盖了 Write 方法,以便重新格式化呈现的输出:

public override void Write(byte[] buffer, int offset, int count)
{
    string html = System.Text.Encoding.UTF8.GetString(buffer);
    //Do some string resplace operations here...
    byte[] input = System.Text.Encoding.UTF8.GetBytes(html);
    m_DefaultStream.Write(input, 0, input.Length);
}

在简单的 HTML 页面 (.html) 上使用它时效果很好,但是当我在 ASPX 页面 (.aspx) 上使用此方法时,Write 方法会被调用多次,将重新格式化分成不同的步骤,并可能破坏字符串替换操作。

我该如何解决这个问题?有没有办法让 ASPX 页面不调用 Write 多次,例如通过更改其缓冲区大小,或者我完全选择了错误的方法,通过使用此 Response.Filter 方法来操作呈现的输出?

4

4 回答 4

2

我只会在 Write 方法中缓冲数据,并在 Close 方法中执行字符串操作,如下所示:

private readonly Stream _forwardStream;
private readonly StringBuilder _sb;

// snip

public override void Write (byte[] buffer, int offset, int count)
{
  string chunk = Encoding.UTF8.GetString (buffer, offset, count);
  _sb.Append (chunk);
}

public override void Close ()
{
  string result = GetManipulatedString ();

  byte[] rawResult = Encoding.UTF8.GetBytes (result);
  _forwardStream.Write (rawResult, 0, rawResult.Length);

  base.Close ();
  _forwardStream.Close ();
}

(如果您在 MemoryStream 中收集数据可能会更好)

于 2009-10-10T09:42:29.250 回答
2

在 Darin Dimitrov 建议的文章的指导下,我完成了以下 Write 方法的实现,该方法也适用于 ASPX 页面:

public override void Write(byte[] buffer, int offset, int count)
{
    string strBuffer = System.Text.UTF8Encoding.UTF8.GetString (buffer, offset, count);

    if (!strBuffer.Contains("</html>"))
    {
        m_ResponseHtml.Append(strBuffer);
    }
    else
    {
        m_ResponseHtml.Append(strBuffer);
        string  html = m_ResponseHtml.ToString ();

        //Do some string operations here...
        byte[] input = System.Text.Encoding.UTF8.GetBytes(html);
        m_DefaultStream.Write(input, 0, input.Length);           
    }
}

该代码利用 StringBuilder (m_ResponseHtml) 来累积整个 HTML,然后对呈现的输出进行实际的字符串操作。

于 2009-10-10T10:22:47.343 回答
1

在附加响应过滤器之前,您可能需要检查内容类型:

var response = m_Application.Context.Response;
if (response.ContentType == "text/html")
{
    response.Filter = new PageStream(m_Application.Context);
}

还有一篇很好的文章描述了 ASP.NET 中的响应过滤器。

于 2009-10-10T08:35:47.380 回答
0

PropellerHead 的响应依赖于在最终缓冲区中找到关闭的 html 标记,但实际上我让最终缓冲区太小而无法包含整个标记。

一种更安全(也更有效)的方法是只在 Write 中进行追加,然后在 Close 中进行字符串操作和输出。

于 2014-06-12T15:21:07.333 回答