我正在使用 ASP.NET MVC,并且正在使用 iTextSharp 将 HTML 页面呈现为 PDF,详细信息是 iTextSharp XMLWorkerHelper 工具。当它们具有纵向方向时,它适用于我必须解析并呈现为 PDF 的所有页面,但是当它们具有横向时它会失败。
这是我想以横向呈现的 HTML 的一个非常简单的示例:
<table style="border:1px solid red; width:280mm;">
<tr>
<td>
In this cell there is a content that can be very large...
</td>
</tr>
</table>
请注意,表格宽度应为 280 毫米(略小于横向模式下的 A4 宽度)。
这里是 HTML 到 PDF 转换的核心:
public override void ExecuteResult(ControllerContext context)
{
IView viewEngineResult;
ViewContext viewContext;
if (string.IsNullOrEmpty(ViewName))
ViewName = context.RouteData.GetRequiredString("action");
context.Controller.ViewData.Model = Model;
var workStream = new MemoryStream();
var sb = new StringBuilder();
Document document = new Document(new Rectangle(842f, 595f));
document.SetPageSize(PageSize.A4.Rotate());
TextWriter tr = new StringWriter(sb);
viewEngineResult = ViewEngines.Engines.FindView(context, ViewName, null).View;
viewContext = new ViewContext(context, viewEngineResult, context.Controller.ViewData,
context.Controller.TempData, tr);
viewEngineResult.Render(viewContext, tr);
Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(sb.ToString()));
PdfWriter pdfWriter = PdfWriter.GetInstance(document, workStream);
pdfWriter.CloseStream = false;
document.Open();
XMLWorkerHelper.GetInstance().ParseXHtml(pdfWriter, document, stream, (Stream)null);
document.Close();
new FileContentResult(workStream.ToArray(), "application/pdf").ExecuteResult(context);
}
结果是横向文档,表格带有红色边框,但宽度错误。很容易理解,PDF 上的渲染宽度不是280mm,而是纵向 A4 文档上表格可能具有的最大宽度。
我尝试了不同的方法:
- 我创建了一个 PdfPTable,将其宽度设置为 100%。然后我在表内创建了一个 PdfPCell。最后,我将 ParseXHtml 结果放入该单元格中。结果是一个完整的“A4 横向宽度”单元格,里面有我的 280 毫米红色边框表格,但宽度通常错误(纵向 A4 文档的最大值)
- 我尝试在执行 ParseXHtml 之前插入 document.NewPage(),因为我在不同的帖子中发现,由于让文档具有正确的尺寸,因此需要调用“NewPage”……但此操作也没有好的结果。
也许我试图遵循错误的方式,并且有一个非常简单和愚蠢的方法来解决这个问题?
提前感谢您的建议。
更新
我试图用一种解决方法来解决这个问题。在document.Open()
和document.Close()
我替换的方法之间:
XMLWorkerHelper.GetInstance().ParseXHtml(pdfWriter, document, stream, (Stream)null);
与以下一个:
var handler = new SampleHandler();
using (TextReader sr = new StringReader(sb.ToString()))
{
//Parse
XMLWorkerHelper.GetInstance().ParseXHtml(handler , sr);
}
foreach (var element in handler.elements)
{
document.Add(element);
}
我创建了一个新类:
public class SampleHandler : IElementHandler
{
public List<IElement> elements = new List<IElement>();
public void Add(IWritable w)
{
if (w is WritableElement)
{
// Here all the logic useful to catch the PDFPTable and redefine
// its width or other tricks (such as nested tables redefining)
}
}
}
正如我在第一个问题中提到的那样,我不知道是否有更简单的方法可以做到这一点。老实说,即使它有效,我也不知道这种解决方法是否好...