HiQPdf throws "Cannot layout the image" when rendering image - c#

I'm working on rendering an image on a pdf document. The rendering is done in C# method like this:
public void PrintPdf(System.Drawing.Image image, string htmlCode, string url)
{
PdfDocument Document = new PdfDocument();
Document.Margins = new PdfDocumentMargins(20, 20, 20, 20);
Document.ImagesCompression = 0;
Document.Compress = false;
Document.SerialNumber = "our-serial-number";
PdfPage page = Document.AddPage(PdfPageSize.A4, Document.Margins, PdfPageOrientation.Portrait);
PdfHtml overlayHtml = new PdfHtml(0, 0, htmlCode, url);
overlayHtml.BrowserWidth = 740;
overlayHtml.MediaType = "print";
PdfLayoutInfo layoutInfo = page.Layout(overlayHtml);
PdfImage pdfImage = new PdfImage(0, (float)115.5, image);
layoutInfo = page.Layout(pdfImage); // <-- this row causes exception from the HiQPdf library
}
The last row throws the following exception from the HiQPdf library. Any thoughts on why?
[HiQPdfException: Cannot layout the image]
HiQPdf.PdfImage.LayoutObject(PdfCanvas objectsContainer) +7243
HiQPdf.PdfPage.Layout(PdfObject pdfObject) +86
This error started happening after we updated HiQPdf version from 5.4.0.0 to 10.17.0.0
The parameters seem ok, there is normal html in htmlCode and I don't see anything wrong with the image either. The image itself can be downloaded as png well as pdf, which works fine.

Related

iTextSharp 5 multiple signatures - last signature renders previous signatures invalid - Document has been altered or corrupted

I am trying to add multiple signatures with iTextSharp 5.5.13.1.
Only the last signature is valid.
And all previous signatures are invalid with the message:
"Document has been altered or corrupted since it was signed" - 1 Page(s) Modified
I don't necessarily need certified signatures.
I use signature append mode but still can't figure out what modifies the document.
In notepad the first part of document till the second signature seems unchanged.
The code I used is:
private string SignFile(string fileToSign, string certname, float xPercent, float yPercent, int page)
{
string signedFile = fileToSign.Replace(".pdf", ".signed.pdf");
using (PdfReader pdfReader = new PdfReader(fileToSign))
{
int pages = pdfReader.NumberOfPages;
var currentSignaturesCount = pdfReader.AcroFields.GetSignatureNames().Count();
using (FileStream signedPdf = new FileStream(signedFile, FileMode.Create, FileAccess.ReadWrite))
{
string tempDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), ".tempfiles");
Directory.CreateDirectory(tempDir);
string tempFileName = Path.Combine(tempDir, Guid.NewGuid().ToString("N") + ".pdf");
if (!File.Exists(tempFileName))
File.Create(tempFileName).Close();
using (PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0', tempFileName, true)) // Append mode
{
// Add signature image
if (page <= pages && page > 0)
{
var pdfContentByte = pdfStamper.GetOverContent(page);
var pageSize = pdfReader.GetPageSize(i);
float pageWidth = pageSize.Width;
float pageHeight = pageSize.Height;
// GenerateStamp() = simplified function that will get a custom bitmap (code not included here)
System.Drawing.Bitmap img = GenerateStamp();
var image = iTextSharp.text.Image.GetInstance(img, true);
image.SetAbsolutePosition(xPercent * pageWidth, pageHeight - yPercent * pageHeight - image.ScaledHeight);
pdfContentByte.AddImage(image);
}
//Also tried adding the image directly to signatureAppearance
//signatureAppearance.SignatureGraphic = image;
//signatureAppearance.SetVisibleSignature(rectangle, page, signatureFieldName);
// and getting the error "Document has been altered or corrupted since it was signed"
PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance;
signatureAppearance.Reason = "Test";
signatureAppearance.SignDate = DateTime.Now;
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC;
signatureAppearance.Acro6Layers = false;
//Also tried like this:
//signatureAppearance.CertificationLevel = currentSignaturesCount == 0 ? PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS : PdfSignatureAppearance.NOT_CERTIFIED;
// with message: "There have been changes made to this document that invalidate the signature"
// sign document
try
{
X509Certificate2 cert = GetCertificateByName(certname);
Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(cert.RawData) };
IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-256");
MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS);
}
catch (Exception ex)
{
throw;
}
}
}
}
return signedFile;
}
Any help is appreciated. Thanks
Your code as is adds an image to the static content of a page. That is forbidden to do to a signed file. For details on allowed and disallowed changes to a signed PDF read this answer.
According to your code comments, though, you also tried to alternatively add the image to the signature appearance. That is not forbidden as such. But analyzing the provided example PDFs it becomes apparent that in this attempt additional content streams have been added to the page. Even though they essentially are empty, this is considered a change of page content which is disallowed.
As it turned out, you didn't add the image to the page content in this attempt but you still retrieved the OverContent of the page:
var pdfContentByte = pdfStamper.GetOverContent(page);
This operation already adds extra content streams to the page for the OverContent to come. Strictly speaking, therefore, the method should be named CreateOrGetOverContent instead...
After removing the GetOverContent call signing does not damage the previous signatures anymore.

Generate PDF from large html

I am generating a PDF from an HTML string.
When this string is really long, I would like to create a new page, split the text (without breaking the html) and so on.
Here is my code :
// instantiate Pdf object
Aspose.Pdf.Generator.Pdf pdf = new Aspose.Pdf.Generator.Pdf();
// specify the Character encoding for for HTML file
pdf.HtmlInfo.CharSet = "UTF-8";
pdf.HtmlInfo.Margin.Left = 10;
pdf.HtmlInfo.Margin.Right = 10;
pdf.HtmlInfo.PageHeight = 1050;
pdf.HtmlInfo.PageWidth = 730;
pdf.HtmlInfo.ShowUnknownHtmlTagsAsText = true;
pdf.HtmlInfo.TryEnlargePredefinedTableColumnWidthsToAvoidWordBreaking = true;
pdf.HtmlInfo.CharsetApplyingLevelOfForce = Aspose.Pdf.Generator.HtmlInfo.CharsetApplyingForceLevel.UseWhenImpossibleDetectFromContent;
// bind the source HTML
pdf.BindHTML("MyVeryVeryLongHTML");
MemoryStream stream = new MemoryStream();
pdf.Save(stream);
byte[] pdfBytes = stream.ToArray();
This code works for the HTML, but the overflow is not handled. The text continue after the page. Is it possible to set a max "height" of the page to not cross, and if it does, it recreates a new page ?
Hope it makes sense !
Thanks a lot
You can set the Page height by selecting type of PDF page you require like A1, A2, etc . Afterwords , your problem of page height will automatically be taken care by the Aspose. For more refer the link..
Aspose PDF Page Height
Update
update pdf.HtmlInfo to pdf.PageSetup (or pdf.PageInfo) and add bottom margin also.

Multiple page HTML not rendering properly in HtmlRenderer.PdfSharp

I have created a sample application in which i have used nuget package HtmlRenderer.PdfSharp
I used the below code in my console application to generate pdf from html:
string input = File.ReadAllText("..//..//HTML//dfdf.html");
PdfDocument document = new PdfDocument();
document.Info.Title = "Test";
PdfPage page = document.AddPage();
XGraphics gfx = XGraphics.FromPdfPage(page);
//XPdfFontOptions options = new XPdfFontOptions(PdfFontEncoding.Unicode, PdfFontEmbedding.Always);
// Create a font
TheArtOfDev.HtmlRenderer.PdfSharp.PdfGenerateConfig pdfconfg = new TheArtOfDev.HtmlRenderer.PdfSharp.PdfGenerateConfig();
pdfconfg.PageSize = PdfSharp.PageSize.A4;
document = PdfGenerator.GeneratePdf(input, pdfconfg);
document.Save("..//..//PDF//dfdf.pdf");
But when the text of html page is very long then it is not rending the content. Only blank pages are generating. Please help. I want to use this library as it provide desired output.

hiqpdf html conversion issue

I am using HiQPdf to convert and combine a list of html page into one pdf document.
this is how i'm doing this:
public class HtmlToPdfEditor
{
private string _firstPage;
private string _secondPage;
//private const string _HiQPdfSerialNumber = "";
private PdfDocument _document;
public HtmlToPdfEditor(string firstPage, string secondPage)
{
_firstPage = firstPage;
_secondPage=secondPage;
}
public void ConvertAll(string outputPath)
{
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
_document = new PdfDocument();
//_document.SerialNumber = _HiQPdfSerialNumber;
string firstPageDoc = GetDocument(_firstPage, "firstPage.pdf");
string secondPageDoc = GetDocument(_secondPage, "secondtPage.pdf");
this.JoinDocument(PdfFromFile(firstPageDoc));
this.JoinDocument(PdfFromFile(secondPageDoc));
_document.WriteToFile(outputPath);
_document.Close();
_document = null;
}
private PdfDocument PdfFromFile(string path)
{
return PdfDocument.FromFile(path);
}
private int JoinDocument(PdfDocument document)
{
var nbPages = _document.Pages.Count;
_document.AddDocument(document);
document.Close();
return nbPages;
}
private string GetDocument(string content, string outputFile)
{
var baseUrl = "";
var htmlToPdfConverter = GetPdfExporter();
htmlToPdfConverter.ConvertHtmlToFile(content, baseUrl, outputFile);
return outputFile;
}
public HtmlToPdf GetPdfExporter()
{
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
//htmlToPdfConverter.SerialNumber = _HiQPdfSerialNumber;
htmlToPdfConverter.Document.PageSize = PdfPageSize.A4;
htmlToPdfConverter.Document.PageOrientation = PdfPageOrientation.Portrait;
htmlToPdfConverter.Document.Margins = new PdfMargins(2);
htmlToPdfConverter.HtmlLoadedTimeout = 60;
htmlToPdfConverter.TriggerMode = ConversionTriggerMode.WaitTime; //Time to load the html
htmlToPdfConverter.WaitBeforeConvert = 1;
return htmlToPdfConverter;
}
}
The issue here is that in the resulting document the page converted from html are displayed as empty pages, only google chrome display them correctly , in firefox these pages continue indefinitely in the loading state.
Notice that if I convert the Html to a PdfDocument instead of storing it to a file and then joining it. The resulting document is perfectly readable but unfortunately I can't use this method.
Any help will be much apreciated!! thx!!
Yes, that's correct, the PDF documents you add to a main document must remain opened until you close the main document.
If the PDF documents you merge are produced from HTML there is actually an easier way to merge the HTML documents in a PDF following the approach from Convert Many HTML to PDF example.
// create an empty PDF document
PdfDocument document = new PdfDocument();
// add a page to document
PdfPage page1 = document.AddPage(PdfPageSize.A4, new PdfDocumentMargins(5),
PdfPageOrientation.Portrait);
try
{
// set the document header and footer before
// adding any objects to document
SetHeader(document);
SetFooter(document);
// layout the HTML from URL 1
PdfHtml html1 = new PdfHtml(textBoxUrl1.Text);
PdfLayoutInfo html1LayoutInfo = page1.Layout(html1);
// determine the PDF page where to add URL 2
PdfPage page2 = null;
System.Drawing.PointF location2 = System.Drawing.PointF.Empty;
if (checkBoxNewPage.Checked)
{
// URL 2 is laid out on a new page with the selected orientation
page2 = document.AddPage(PdfPageSize.A4, new PdfDocumentMargins(5),
GetSelectedPageOrientation());
location2 = System.Drawing.PointF.Empty;
}
else
{
// URL 2 is laid out immediately after URL 1 and html1LayoutInfo
// gives the location where the URL 1 layout finished
page2 = document.Pages[html1LayoutInfo.LastPageIndex];
location2 = new System.Drawing.PointF(html1LayoutInfo.LastPageRectangle.X,
html1LayoutInfo.LastPageRectangle.Bottom);
}
// layout the HTML from URL 2
PdfHtml html2 = new PdfHtml(location2.X, location2.Y, textBoxUrl2.Text);
page2.Layout(html2);
// write the PDF document to a memory buffer
byte[] pdfBuffer = document.WriteToMemory();
// inform the browser about the binary data format
HttpContext.Current.Response.AddHeader("Content-Type", "application/pdf");
// let the browser know how to open the PDF document
HttpContext.Current.Response.AddHeader("Content-Disposition",
String.Format("attachment; filename=LayoutMultipleHtml.pdf;
size={0}",
pdfBuffer.Length.ToString()));
// write the PDF buffer to HTTP response
HttpContext.Current.Response.BinaryWrite(pdfBuffer);
// call End() method of HTTP response
// to stop ASP.NET page processing
HttpContext.Current.Response.End();
}
finally
{
document.Close();
}
Ok I resolved this issue by ensuring that all pdf documents to be merged are closed after closing the final document. In other words the method JoinDocument will no longer call document.Close(). I'll call it later after closing the final document (_document).

XpsDocument ignores my height settings

I am facing a problem when I try to declare a PageHeight on an XPS Document.
My code so far looks like this:
private FixedDocumentSequence GetDocument(DocumentPaginator paginator)
{
FixedDocumentSequence document = null;
string tempFileName = System.IO.Path.GetTempFileName();
File.Delete(tempFileName);
using (var xpsDocument = new XpsDocument(tempFileName, FileAccess.ReadWrite, CompressionOption.NotCompressed))
{
var writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
var printTicket = new PrintTicket
{
PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4, paginator.PageSize.Width, paginator.PageSize.Height),
PageBorderless = PageBorderless.Borderless,
PageMediaType = PageMediaType.None,
};
writer.Write(paginator, printTicket);
//paginator.PageSize.Height = 1122
var d = xpsDocument.GetFixedDocumentSequence();
//d.DocumentPaginator.PageSize.Height = 1056
document = d;
}
return document;
}
The Problem is that I am declaring a PageSize Height of 1122 which I am getting from this code:
var pd = new PrintDialog();
var sz = new Size(pd.PrintableAreaWidth, pd.PrintableAreaHeight);
but when I look into the property
d.DocumentPaginator.PageSize.Height
I can see that the Height is 1056, this height happens to be the Height of the NorthAmericanLetter Page format height, I am already specifying a specific printTicket with an explicit PageMediaSize what else could be wrong?
Edit:
Here is my edited code, but this give the same result:
private FixedDocumentSequence GetDocument(DocumentPaginator paginator)
{
FixedDocumentSequence document = null;
string oldTempFileName = System.IO.Path.GetTempFileName();
File.Delete(oldTempFileName);
XpsDocument oldXpsDocument;
using (oldXpsDocument = new XpsDocument(oldTempFileName, FileAccess.ReadWrite, CompressionOption.NotCompressed))
{
var writer = XpsDocument.CreateXpsDocumentWriter(oldXpsDocument);
var printTicket = new PrintTicket
{
PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4, paginator.PageSize.Width, paginator.PageSize.Height),
PageBorderless = PageBorderless.Borderless,
PageMediaType = PageMediaType.None,
};
writer.Write(paginator, printTicket);
}
//string newTempFileName = System.IO.Path.GetTempFileName();
//File.Delete(newTempFileName);
using (var newXpsDocument = new XpsDocument(oldTempFileName, FileAccess.Read, CompressionOption.NotCompressed))
{
var d = newXpsDocument.GetFixedDocumentSequence();
document = d;
}
return document;
}
I looked into the file that got created with the first using block and I still can see that the height of the pages is 1056, output of the 1.fpage file:
<FixedPage
xmlns="http://schemas.microsoft.com/xps/2005/06" xmlns:x="http://schemas.microsoft.com/xps/2005/06/resourcedictionary-key"
xml:lang="und"
Width="816" Height="1056">
<FixedPage.Resources>
<ResourceDictionary>
<LinearGradientBrush x:Key="b0" StartPoint="33,0" EndPoint="33,23" ColorInterpolationMode="SRgbLinearInterpolation" MappingMode="Absolute" SpreadMethod="Pad">
Edit2:
Found the a solution for my problem.
In my DocumentPaginator I had to override the GetPage Method and there I return a new DocumentPage(visual), this constructor has an overload that lets me set the PageSize only if I set it there its setting the PageSizes correctly.
http://msdn.microsoft.com/en-us/library/system.windows.documents.documentpage(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/ms597306(v=vs.110).aspx
My previous code:
public override DocumentPage GetPage(int pageNumber)
{
// create page element (PageTemplate is a custom usercontrol that can hold content)
var page = new PageTemplate(this, pageNumber + 1);
// arrange the elements on the page
page.Arrange(new Rect(0, 0, PageSize.Width, PageSize.Height));
// return new document page
return new DocumentPage(page);
}
Now with the second contructor:
public override DocumentPage GetPage(int pageNumber)
{
// create page element (PageTemplate is a custom usercontrol that can hold content)
var page = new PageTemplate(this, pageNumber + 1);
// arrange the elements on the page
page.Arrange(new Rect(0, 0, PageSize.Width, PageSize.Height));
// return new document page
return new DocumentPage(page, PageSize, new Rect(0, 0, 10, 10), new Rect());
}
The problem is that you're expecting the xpsDocument to have the same dimensions of the file that you created.
When you create an XpsDocument, its going to have a default FixedDocumentSequence. Since you're creating an XpsDocument, and not opening one, you're getting the default fixed document sequence, which is why you are seeing 1056 as the height--default that is the default.
However, if you look at the code example at the bottom of FixedDocumentSequence, you'll see LoadDocumentViewer, where it replaces an old XpsDocument with a new one.
When you call writer.Write(paginator, printTicket); it will write an XpsDocument to the file you specified using the PrintTicket you provided. Now you need to create an XpsDocument using that file path, and when you open it, you can then get the FixedDocumentSequence of that document and the sizes with match the PrintTicket properties. So in pseudo-code, you should do this:
string fileName = ...
using Create XpsDocument at fileName
Create XpsDocumentWriter
Create and setup PrintTicket
Write to the file using your DocumentPaginator and PrintTicket
using Create XpsDocument reading from fileName
document = opened XpsDocument GetFixedDocumentSequence()
Edit:
Good find in your last edit. I printed an XPS document using MS Word with the A4 sized setting and all the pages come up as 1056 x 816 also. I then created an XPS document using the A3 size and that comes up as 1587.36 x 1122.56. There is clearly something going on internally that we cannot see; my guess is that since the page sizes are similar in dimension, it just uses the 1056 x 816 dimensions? Who really knows... I would suggest filing a bug report to Microsoft.
In the meantime, maybe try to change d.DocumentPaginator.PageSize or even d.PrintTicket objects and try to get the page size to change that way. If there is a way to enumerate the FixedPage's you could change their settings manually too.

Categories

Resources