2015-11-26 2 views
0

Я пытаюсь сделать PDF с нижним колонтитулом на нем с помощью iTextSharper. Это работает нормально, по большей части. Я хочу добавить нижний колонтитул на каждую страницу.Нижний колонтитул с содержимым PDF с использованием iTextSharp

Мой код делает добавить колонтитул правильно, однако, текст перекрывается с содержанием PDF, как вы можете видеть на картинке: pdf

действия контроллера:

public ActionResult GeneratePDF(int id) 
{ 
    Order order = db.Orders.Where(x => x.ID == id).SingleOrDefault(); 
    return new HFPdfResult(order, "OrderPDF"); 
} 

HFPdfResult (ViewResult) класс:

using System.Web.Mvc; 
using RentproDC.Models.RazorPDF; 

namespace RentproDC.Models.RazorPDF 
{ 
    public class HFPdfResult : ViewResult 
    { 
     //Constructors 
     public HFPdfResult(object model, string name) 
     { 
      ViewData = new ViewDataDictionary(model); 
      ViewName = name; 
     } 

     public HFPdfResult() : this(new ViewDataDictionary(), "Pdf") 
     { 
     } 

     public HFPdfResult(object model) : this(model, "Pdf") 
     { 
     } 

     //Override FindView to load PdfView 
     protected override ViewEngineResult FindView(ControllerContext context) 
     { 
      var result = base.FindView(context); 
      if (result.View == null) 
       return result; 

      var pdfView = new HFPdfView(result); 
      return new ViewEngineResult(pdfView, pdfView); 
     } 
    } 
} 

класс HFPdfView:

using System; 
using System.Collections; 
using System.IO; 
using System.Text; 
using System.Web.Mvc; 
using System.Xml; 
using iTextSharp.text; 
using iTextSharp.text.html; 
using iTextSharp.text.pdf; 
using iTextSharp.text.xml; 
using iTextSharp.text.html.simpleparser; 
using System.Collections.Generic; 

namespace RentproDC.Models.RazorPDF 
{ 
    public class HFPdfView : IView, IViewEngine 
    { 
     private readonly ViewEngineResult _result; 

     public HFPdfView(ViewEngineResult result) 
     { 
      _result = result; 
     } 

     public void Render(ViewContext viewContext, TextWriter writer) 
     { 
      // generate view into string 
      var sb = new System.Text.StringBuilder(); 
      TextWriter tw = new System.IO.StringWriter(sb); 
      _result.View.Render(viewContext, tw); 
      var resultCache = sb.ToString(); 

      // detect itext (or html) format of response 
      XmlParser parser; 
      using (var reader = GetXmlReader(resultCache)) 
      { 
       while (reader.Read() && reader.NodeType != XmlNodeType.Element) 
       { 
        // no-op 
       } 

       if (reader.NodeType == XmlNodeType.Element && reader.Name == "itext") 
        parser = new XmlParser(); 
       else 
        parser = new HtmlParser(); 
      } 

      // Create a document processing context 
      var document = new Document(PageSize.A4, 36, 36, 36, 120); 
      document.Header = new HeaderFooter(new Phrase("Test header"), false); 
      document.Open(); 

      // associate output with response stream 
      var pdfWriter = PdfWriter.GetInstance(document, viewContext.HttpContext.Response.OutputStream); 
      pdfWriter.PageEvent = new PdfFileEvents(); 
      pdfWriter.CloseStream = false; 

      // this is as close as we can get to being "success" before writing output 
      // so set the content type now 
      viewContext.HttpContext.Response.ContentType = "application/pdf"; 

      // parse memory through document into output 
      using (var reader = GetXmlReader(resultCache)) 
      { 
       parser.Go(document, reader); 
      } 

      pdfWriter.Close(); 
     } 

     private static XmlTextReader GetXmlReader(string source) 
     { 
      byte[] byteArray = Encoding.UTF8.GetBytes(source); 
      MemoryStream stream = new MemoryStream(byteArray); 

      var xtr = new XmlTextReader(stream); 
      xtr.WhitespaceHandling = WhitespaceHandling.None; // Helps iTextSharp parse 
      return xtr; 
     } 

     public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, 
      bool useCache) 
     { 
      throw new System.NotImplementedException(); 
     } 

     public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, 
      bool useCache) 
     { 
      throw new System.NotImplementedException(); 
     } 

     public void ReleaseView(ControllerContext controllerContext, IView view) 
     { 
      _result.ViewEngine.ReleaseView(controllerContext, _result.View); 
     } 
    } 

    public class PdfFileEvents : PdfPageEventHelper 
    { 
     public override void OnEndPage(PdfWriter pi, Document doc) 
     { 
      PdfContentByte cb = pi.DirectContent; 
      ColumnText ct = new ColumnText(cb); 

      List list = new List(List.ORDERED); 
      string text = "<ol><li><span style='color: rgb(34, 34, 34); font-family: arial, sans-serif; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 16.12px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; display: inline !important; float: none; background-color: rgb(255, 255, 255); font-size: 9px;'>"+RentProModels.Models.Settings.Get("CompanyName") + "<br />" + RentProModels.Models.Settings.Get("CompanyTelephone") + "<br />" + 
       RentProModels.Models.Settings.Get("CompanyEmail") + "<br />" + 
       "KVK " + "1234568789" + "<br />" + 
       "Bank ABN01Blahh12341</span></li></ol>"; 
      ArrayList htmlarraylist = HTMLWorker.ParseToList(new StringReader(text), null); 
      for (int k = 0; k < htmlarraylist.Count; k++) 
      { 
       list.Add((IElement)htmlarraylist[k]); 
      } 
      ct.AddElement(list); 
      ct.SetSimpleColumn(500, 79, 900, 5); //curPos = verder naar boven 
      ct.Go(); 
     } 

     public override void OnStartPage(PdfWriter pi, Document doc) 
     { 
      PdfContentByte cb = pi.DirectContent; 
      ColumnText ct = new ColumnText(cb); 

      cb.BeginText(); 
      cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 12.0f); 
      cb.SetTextMatrix(doc.LeftMargin, doc.PageSize.Height - doc.TopMargin); 
      cb.ShowText(String.Format("{0} {1}", "Dit is een", "Header")); 
      cb.EndText(); 
     } 

    } 
} 

вид заказа (он загружает Order объект в этой точке зрения, и создает PDF, основанный на том, что):

@model RentPro.Models.Tables.Order 
@using RentProModels.Models 
@using RentPro.Models.Tables 
@{ 
    Layout = null; 
} 
<!DOCTYPE html> 
<html> 
<head> 
    <meta name="viewport" content="width=device-width" /> 
    <title></title> 
</head> 
<body style="font-size: 12px;"> 
    <table width="100%" widths="60;40"> 
     <row> 
      <td> 
       <newline /> 
       <newline /> 
       <h2 style="text-decoration:underline;">Pakbon</h2> 
      </td> 
      <td> 
       @*    <img url="@System.Web.Hosting.HostingEnvironment.MapPath("/")@Settings.Get("PicturesPath") /../Images/@Settings.Get("LogoFile")" width="239" height="83" />*@ 
       <newline /> 
       <newline /> 
      </td> 
     </row> 
    </table> 
    <table width="100%" cellpadding="0.0" widths="50;17;30"> 
     @if (@Model.Delivery.Company != "nvt") 
     { 
      <row> 
       <cell> 
        <p style="font-weight:bold;">@Model.Delivery.Company</p> 
       </cell> 
       <cell></cell> 
       <cell></cell> 
      </row> 
     } 
     <row> 
      <cell><p style="font-weight:bold;">@Model.Delivery.FirstName @Model.Delivery.LastName</p></cell> 
      <cell>Order Nr:</cell> 
      <cell>@Model.ID</cell> 
     </row> 
     <row> 
      <cell><p style="font-weight:bold;">@Model.Delivery.StreetName @Model.Delivery.HouseNumber</p></cell> 
      <cell>Order Datum:</cell> 
      <cell>@Model.PlaceDate.ToShortDateString()</cell> 
     </row> 
     <row> 
      <cell><p style="font-weight:bold;">@Model.Delivery.ZipCode, @Model.Delivery.City</p></cell> 
      <cell>Transport:</cell> 
      <cell>@Model.TransportCarrier.Name</cell> 
     </row> 
     <row> 
      <cell><p style="font-weight:bold;">@Model.Phonenumber</p></cell> 
      <cell>Start Datum:</cell> 
      <cell>@Model.StartDate.ToShortDateString()</cell> 
     </row> 
     <row> 
      @{ string KVKofBTW; 
       if (Model.KVKnummer != null && Model.KVKnummer != "") 
       { 
        if (Model.Billing.Country.Name == "Nederland") 
        { 
         KVKofBTW = "KVK:"; 
        } 
        else 
        { 
         KVKofBTW = "BTW:"; 
        } 
       } 
       else 
       { 
        KVKofBTW = ""; 
       } 
      } 
      <cell><p style="font-weight:bold;">@KVKofBTW @Model.KVKnummer</p></cell> 
      <cell>Eind Datum:</cell> 
      <cell>@Model.EndDate.ToShortDateString()</cell> 
     </row> 
     <row> 
      <cell></cell> 
      <cell>Aantal Dagen:</cell> 
      <cell>@((Model.EndDate.Date - Model.StartDate.Date).Days + 1)</cell> 
     </row> 
     <row> 
      <cell>Opmerkingen:</cell> 
      <cell></cell> 
      <cell></cell> 
     </row> 
     <row> 
      <cell colspan="3">@Model.Note</cell> 
     </row> 
    </table> 
    <table width="100%" widths="10;60" cellpadding="2"> 
     <row> 
      <cell> 
       <newline /> 
      </cell> 
      <cell></cell> 
     </row> 
     <row> 
      <cell><p style="font-style:italic;">Aantal</p></cell> 
      <cell><p style="font-style:italic;">Artikel</p></cell> 
     </row> 
     @foreach (var item in Model.Items) 
     { 
      <row> 
       <cell>@item.ProductCode</cell> 
       <cell>@item.Amount</cell> 
       <cell>@item.ProductTitle</cell> 
       <cell> [ ]</cell> 
       <cell> [ ]</cell> 
       <cell> [ ]</cell> 
      </row> 
      if (RentProModels.Models.Settings.GetBool("PakBonAccessory")) 
      { 
       foreach (RentPro.Models.Tables.Accessory accesory in item.Product.Accessories) 
       { 
        <row> 
         <cell></cell> 
         <cell></cell> 
         <cell>@accesory.Name</cell> 
         <cell> [ ]</cell> 
         <cell> [ ]</cell> 
         <cell> [ ]</cell> 
        </row> 
       } 

      } 

     } 
    </table> 
    <table width="100%" widths="60;50"> 
     <row> 
      <cell> 
       <newline /> 
       <newline /> 
       <newline /> 
       <newline /> 
       <newline /> 
       <newline /> 
      </cell> 
      <cell></cell> 
     </row> 
     <row> 
      <cell>Handtekening voor ontvangst:</cell> 
      <cell>Retour ontvangen door:</cell> 
     </row> 
     <row> 
      <cell>Naam Klant:</cell> 
      <cell>Naam:</cell> 
     </row> 
     <row> 
      <cell>Handtekening:</cell> 
      <cell>Handtekening:</cell> 
     </row> 
    </table> 
</body> 
</html> 

Я видел SO отправить о настройке размера документа, я могу это сделать, но это не похоже на работу:

var document = new Document(PageSize.A4, 36, 36, 36, 120); 

Я дал ему запас 120 пользовательских единиц на нижней стороне, и я использую только 110, так почему она до сих пор перекрытием?

Любая помощь была бы принята с благодарностью.

+1

Это ** пользовательских единиц **, не * пикселей *. Это ** iTextSharp **, а не iTextSharper. Вы должны использовать XML Worker, а не 'HTMLWorker'. Что касается вашего вопроса: я не вижу достаточной информации, которая позволяет кому-либо ответить на него. Какую версию iTextSharp вы используете? Как вы добавляете другой контент? –

+0

Привет, Бруно, спасибо за ваш ответ. Я прочитал ваш оригинальный комментарий, но, к сожалению, это решение не сработало. Спасибо, что указали, что это iTextSharp, но я перепутал его с плагином ReSharper. То же самое с пикселями. – nbokmans

+0

Вам необходимо предоставить дополнительную информацию. У вас есть [SSCCE] (http://sscce.org)? Когда я пытаюсь достичь той же цели, я не могу воспроизвести вашу проблему. –

ответ

0

После некоторого беспорядка я решил, что лучше всего обновить мой проект, чтобы использовать более новую версию iTextSharp.

Я полностью избавился от библиотеки RazorPDF и теперь работает с iTS 5.5.8. Я думал, что поделился бы моим обновленным кодом, если все будут сталкиваться с этой проблемой.

Это также устранило проблему в моем OP о нижнем колонтитуле, перекрывающемся с содержимым PDF.

Новый код:

public class RazorPdf 
{ 
    public static byte[] GeneratePdf(string html, 
     System.Collections.Generic.List<PdfPageContent> headerAndFooterContent = null) 
    { 
     Byte[] bytes; 
     using (var ms = new MemoryStream()) 
     { 
      using (var doc = new Document(PageSize.A4, 40f, 40f, 30f, 50f)) 
      { 
       using (var writer = PdfWriter.GetInstance(doc, ms)) 
       { 
        doc.Open(); 
        var example_css = @".headline{font-size:200%}"; //incase you want to parse css 
        writer.PageEvent = new PageEventHelper(headerAndFooterContent); 
        using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) 
        { 
         using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(html))) 
         { 
          iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss); 
         } 
        } 

        doc.Close(); 
       } 
      } 
      bytes = ms.ToArray(); 
     } 
     return bytes; 
    } 
} 

public class PageEventHelper : PdfPageEventHelper 
{ 
    private PdfContentByte _cb; 
    private PdfTemplate _template; 

    private readonly System.Collections.Generic.List<PdfPageContent> _content = null; 

    public PageEventHelper(System.Collections.Generic.List<PdfPageContent> content) 
    { 
     _content = content; 
    } 

    public override void OnOpenDocument(PdfWriter writer, Document document) 
    { 
     _cb = writer.DirectContent; 
     _template = _cb.CreateTemplate(50, 50); 
    } 

    public override void OnEndPage(PdfWriter writer, Document document) 
    { 
     base.OnEndPage(writer, document); 

     /* Contents */ 
     if (_content != null) 
     { 
      foreach (PdfPageContent ppc in _content) 
      { 
       ColumnText ct = new ColumnText(GetCb(writer)); 
       Phrase phrase = new Phrase(new Chunk(ppc.Content, FontFactory.GetFont(FontFactory.HELVETICA, 12, Font.NORMAL))); 
       switch (ppc.Location) 
       { 
        case PdfPageLocation.Header: 
         ct.SetSimpleColumn(phrase, 40, 700, 530, 840, 25, ppc.Alignment); 
         break; 
        case PdfPageLocation.Footer: 
         ct.SetSimpleColumn(phrase, 40, 100, 530, 20, 25, ppc.Alignment); 
         break; 
       } 
       ct.Go(); 
      } 
     } 

     /* Page number */ 
     string text = writer.PageNumber.ToString(); 
     BaseFont font = BaseFont.CreateFont(); 
     float len = font.GetWidthPoint(text, 12); 

     Rectangle pageSize = document.PageSize; 

     GetCb(writer).SetRGBColorFill(100, 100, 100); 

     GetCb(writer).BeginText(); 
     GetCb(writer).SetFontAndSize(font, 12); 
     GetCb(writer).SetTextMatrix(document.RightMargin, pageSize.GetBottom(document.BottomMargin)); 
     GetCb(writer).ShowText(text); 
     GetCb(writer).EndText(); 

     GetCb(writer).AddTemplate(GetTemplate(writer), document.RightMargin - len, 0); 
    } 

    private PdfContentByte GetCb(PdfWriter writer) 
    { 
     return _cb ?? (_cb = writer.DirectContent); 
    } 

    private PdfTemplate GetTemplate(PdfWriter writer) 
    { 
     return _template ?? (_template = GetCb(writer).CreateTemplate(50, 50)); 
    } 
} 

public class PdfPageContent 
{ 
    public PdfPageLocation Location { get; set; } 
    public int Alignment { get; set; } 
    public string Content { get; set; } 
} 

public enum PdfPageLocation 
{ 
    Footer = 1, 
    Header = 2 
} 

ControllerExtension:

public class Controller : System.Web.Mvc.Controller 
    { 
     public FileContentResult PdfFileResult(string viewPath, object model = null) 
     { 
      List<PdfPageContent> content = new List<PdfPageContent>(); 
      content.Add(new PdfPageContent() { Location = PdfPageLocation.Footer, Alignment = Element.ALIGN_LEFT, Content = "FOOTER LEFT" }); 
      content.Add(new PdfPageContent() { Location = PdfPageLocation.Footer, Alignment = Element.ALIGN_RIGHT, Content = "FOOTER RIGHT" }); 
      content.Add(new PdfPageContent() { Location = PdfPageLocation.Header, Alignment = Element.ALIGN_LEFT, Content = "HEADER LEFT" }); 
      content.Add(new PdfPageContent() { Location = PdfPageLocation.Header, Alignment = Element.ALIGN_RIGHT, Content = "HEADER RIGHT" }); 
      return new FileContentResult(RazorPdf.GeneratePdf(RenderViewToString(viewPath, model), content), "application/pdf"); 

     } 

     public bool SavePdfFileResult(string viewPath, string relativeFilePath, object model = null) 
     { 
      byte[] data = RazorPdf.GeneratePdf(RenderViewToString(viewPath, model)); 
      if (!string.IsNullOrWhiteSpace(relativeFilePath)) 
      { 
       try 
       { 
        System.IO.File.WriteAllBytes(Server.MapPath(relativeFilePath), data); 
       } 
       catch (Exception e) 
       { //In case of exception, file write has failed 
        return false; 
       } 
       return true; 
      } 
      return false; 
     } 

     public string RenderViewToString(string viewPath, object model = null, bool partial = false) 
     { 
      ViewEngineResult viewEngineResult = partial ? ViewEngines.Engines.FindPartialView(ControllerContext, viewPath) : 
       ViewEngines.Engines.FindView(ControllerContext, viewPath, null); 

      if (viewEngineResult == null) 
       throw new FileNotFoundException("View cannot be found."); 

      var view = viewEngineResult.View; 
      ControllerContext.Controller.ViewData.Model = model; 

      string result = null; 

      using (var sw = new StringWriter()) 
      { 
       var ctx = new ViewContext(ControllerContext, view, ControllerContext.Controller.ViewData, ControllerContext.Controller.TempData, sw); 
       view.Render(ctx, sw); 
       result = sw.ToString(); 
      } 
      return result; 
     } 
    } 

Использование в контроллере:

public ActionResult GeneratePDF(int id) 
    { 
     Order order = db.Orders.SingleOrDefault(x => x.ID == id); 
     return PdfFileResult("/Views/Order/OrderPDF.cshtml", order); 
    } 
Смежные вопросы