3

因此,我在内存中渲染部分视图,以便将视图中的 XSL-FO 数据定向到 PDF 渲染器。

PDF 渲染器可以将字符串、XmlDocument 或 Stream 作为输入。

这是我想做的事情:(为清楚起见已编辑

解决方案取自:http ://thriftybliss.spaces.live.com/blog/cns!58DA805F37F31F20!170.entry?wa=wsignin1.0&sa=362921628

var viewPage = new ViewPage();
var viewData = new ViewDataDictionary(model);
viewPage.ViewData = viewData;

var control = viewPage.LoadControl(viewName);
viewPage.Controls.Add(control);

using (var inStream = new MemoryStream())
{
    using (var sw = new StreamWriter(inStream))
    {
        using (var tw = new HtmlTextWriter(sw))
        {
            viewPage.RenderControl(tw);
        }
        using (var outStream = new MemoryStream())
        {
            driver.Render(inStream, outStream);
            return outStream.ToArray();
        }
    }
}

这是有效的方法,但我宁愿不这样做:

var sb = new StringBuilder();

using (var sw = new StringWriter(sb))
{
    using (var tw = new HtmlTextWriter(sw))
    {
        vp.RenderControl(tw);
    }
}

var xml = new XmlDocument();
xml.LoadXml(sb.ToString());

using (var ms = new MemoryStream())
{
    driver.Render(xml, ms);
    return ms.ToArray();
}

不幸的是,HtmlTextWriter 似乎不想写入 StreamWriter,或者我只是搞砸了别的东西。

如果我用 StringWriter 替换 StreamWriter 它可以正常工作,但我不能使用 StringWriter 因为当我调用 .ToString() 时,我会得到各种混淆 XSL-FO 的转义字符,并且渲染器会抛出“非法字符”异常。

我通过创建一个 XmlDocument 并将字符串加载到其中解决了这个问题,但这似乎是一种非常迂回的做事方式。我真的只想捕获 HtmlTextWriter 的输出并将其直接输入到渲染器中。有没有办法做到这一点?

谢谢!

4

2 回答 2

1

当您说“HtmlTextWriter 似乎不想写入 StreamWriter”时,这是否意味着driver.Render无法从 inStream 中获取任何字节?我能想到的两种可能...

首先是 HtmlTextWriter 在完成写入后不会刷新流,在这种情况下,在sw.Flush()将 inStream 交给driver.Render.

其次,在写入 MemoryStream 之后,位置指针将位于流的末尾,任何从它读取的尝试都将产生零字节(因为它位于末尾)。

在这种情况下,设置inStream.Position为 0,或者在调用inStream.Seek(0, SeekOrigin.Begin)之前调用driver.Render应该可以修复它。

我之前遇到过几次第二种情况,所以这是我最好的猜测。

于 2010-08-30T17:28:08.983 回答
-1

我根本没有测试过这个。..但它是我在其他地方制作和使用的RenderViewToString 方法的修改版本:

    public static Stream RenderViewToStream<T>(string viewPath, T model, ControllerContext controllerContext)
    {
        var ms = new MemoryStream();
        using (var writer = new StreamWriter(ms))
        {
            var view = new WebFormView(viewPath);
            var vdd = new ViewDataDictionary<T>(model);
            var viewCxt = new ViewContext(controllerContext, view, vdd, new TempDataDictionary(), writer);
            viewCxt.View.Render(viewCxt, writer);
        }
        return ms;
    }
于 2010-08-30T16:57:54.117 回答