Not able to get Unicode support for different languages - c#

public PDFFormFillerResult CreateHtmlToPdfMemoryStream(string sHtmlText)
{
//Create a stream that we can write to, in this case a MemoryStream
using (var ms = new MemoryStream())
{
//Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
var doc = new iTextSharp.text.Document();
//Create a writer that's bound to our PDF abstraction and our stream
var writer = PdfWriter.GetInstance(doc, ms);
//Open the document for writing
doc.Open();
var example_html = sHtmlText;
//Create a new HTMLWorker bound to our document
var htmlWorker = new iTextSharp.text.html.simpleparser.HTMLWorker(doc);
FontFactory.Register(Path.Combine(Environment.CurrentDirectory + "\\Library\\arial.ttf"), "Arial"); // just give a path of arial.ttf
StyleSheet css = new StyleSheet();
css.LoadTagStyle("body", "face", "Garamond");
css.LoadTagStyle("body", "encoding", "Identity-H");
css.LoadTagStyle("body", "size", "12pt");
htmlWorker.SetStyleSheet(css);
// htmlWorker.StartDocument();
//HTMLWorker doesn't read a string directly but instead needs a TextReader (which StringReader subclasses)
using (var sr = new StringReader(example_html)) // using (TextReader sr = new StreamReader(example_html, Encoding.UTF8))
{
//Parse the HTML
htmlWorker.Parse(sr);
}
doc.Close();
return new PDFFormFillerResult(ms, PDFFormFillerResultType.Success, string.Empty);
}
}
I need the output as ByteStream as I am merging multiple documents to create one pdf at the end. This works well for English, but when I try using other languages like Russian, Korean, Combodian, etc only the english text which are in template gets displayed.

Related

How to read marge fillable pdf data using itextsharp

I have two fillable pdf files and did the code to merge those pdfs into one single pdf. Below is my code for that.
public void PDFSplit()
{
List<string> files=new List<string>();
files.Add(Server.MapPath("~/Template/sample_pdf.pdf"));
files.Add(Server.MapPath("~/Template/temp/sample_pdf.pdf"));
//call method
Merge(files, Server.MapPath("~/Template/sample_pdf_123.pdf"));
}
//Merge pdf
public void Merge(List<String> InFiles, String OutFile)
{
using (FileStream stream = new FileStream(OutFile, FileMode.Create))
using (iTextSharp.text.Document doc = new iTextSharp.text.Document())
using (PdfCopy pdf = new PdfCopy(doc, stream))
{
doc.Open();
PdfReader reader = null;
PdfImportedPage page = null;
InFiles.ForEach(file =>
{
reader = new PdfReader(file);
for (int i = 0; i < reader.NumberOfPages; i++)
{
page = pdf.GetImportedPage(reader, i + 1);
pdf.AddPage(page);
}
pdf.FreeReader(reader);
reader.Close();
});
}
}
The code is working fine, but the problem is when I am trying to read that new generated merged file, it's not showing fields using AcroFields.
//To read pdf data
PdfReader reader = null;
reader = new PdfReader(Server.MapPath("~/Template/sample_pdf_123.pdf"));
AcroFields pdfFormFields = reader.AcroFields;
You are unable to marge fallible PDF files because you are using an old version of iText. Please upgrade to iText 7 for .NET and read the iText 7 jump-start tutorial, more specifically chapter 6 where it says:
Merging forms
This is how it's done:
PdfDocument destPdfDocument = new PdfDocument(new PdfWriter(dest));
PdfDocument[] sources = new PdfDocument[] {
new PdfDocument(new PdfReader(SRC1)),
new PdfDocument(new PdfReader(SRC2)) };
PdfPageFormCopier formCopier = new PdfPageFormCopier();
foreach (PdfDocument sourcePdfDocument in sources) {
sourcePdfDocument.CopyPagesTo(1,
sourcePdfDocument.GetNumberOfPages(), destPdfDocument, formCopier);
sourcePdfDocument.Close();
}
destPdfDocument.Close();

merging pdf and preserve SetTagged

I'm using iTextSharp 5.x. I'm trying to merge two pdfs and preserve the isTagged flag. When I remove copy.SetTagged(); the result pdf contains both pdfs which is great. When adding the copy.SetTagged() is get an exception
Exception -->System.ObjectDisposedException: Cannot access a closed file.
at System.IO.__Error.FileNotOpen()
at System.IO.FileStream.get_Position()
Here is the code
List<string> filesToMerge = new List<string> { "C:/dev/dcs/wp-cla-dcs/Hex/Docs/metadata/coverPage.pdf", "C:/dev/dcs/wp-cla-dcs/Hex/Docs/metadata/49W7a.pdf" };
string outputFileName = "C:/dev/dcs/wp-cla-dcs/Hex/Docs/metadata/results.pdf";
using (FileStream outFS = new FileStream(outputFileName, FileMode.Create))
using (Document document = new Document())
// using (PdfCopy copy = new PdfCopy(document, outFS))
using (PdfCopy copy = new PdfSmartCopy(document, outFS))
{
{
copy.SetTagged();
// Set up the iTextSharp document
document.Open();
foreach (string pdfFile in filesToMerge)
{
using (var reader = new PdfReader(pdfFile))
{
copy.AddDocument(reader);
copy.FreeReader(reader);
}
}
}
}
despite #bruno-lowagie's comment, I have had better results doing this with with iText5.
Uisng iText7, PdfMerger left several contents untagged (all were tagged in the source document). PdfCopy in iText5 however worked just fine, only needed to manually add Xmp metadata, title, lang, etc:
public static void CombineMultiplePDFs(string[] fileNames, string outFile)
{
var lang = "en";
var title = "My new title";
// step 1: creation of a document-object
Document document = new Document();
// step 2: we create a writer that listens to the document
FileStream newFileStream = new FileStream(outFile, FileMode.Create);
PdfCopy writer = new PdfCopy(document, newFileStream);
writer.SetTagged();
writer.PdfVersion = PdfWriter.VERSION_1_7;
writer.AddViewerPreference(PdfName.DISPLAYDOCTITLE, new PdfBoolean(true));
writer.Info.Put(PdfName.TITLE, new PdfString(title));
writer.CreateXmpMetadata();
// step 3: we open the document
document.Open();
// set meta data
document.AddLanguage(lang);
document.AddTitle(title);
// keep an array of all open readers so they can be closed again.
var readers = new PdfReader[fileNames.Length];
for (var fi = 0; fi < fileNames.Length; fi++)
{
// we create a reader for a certain document
var fileName = fileNames[0];
PdfReader reader = new PdfReader(fileName);
readers[fi] = reader;
reader.ConsolidateNamedDestinations();
// step 4: we add content
for (int i = 1; i <= reader.NumberOfPages; i++)
{
// IMPORTANT: the third param is is "KeepTaggedPdfStructure"
PdfImportedPage page = writer.GetImportedPage(reader, i, true);
writer.AddPage(page);
}
}
// step 5: we close the document and writer
writer.Close();
document.Close();
// close readers only after document is lcosed
foreach (var r in readers)
{
r.Close();
}
}

Convert html to pdf and merge it with existing pdfs

I have a System.Net.Mail.MailMessage which shall have it's html body and pdf attachments converted into one single pdf.
Converting the html body to pdf works for me with this answer
Converting the pdf attachments into one pdf works for me with this answer
However after ~10 hours of trying I can not come up with a combined solution which does both. All I'm getting are NullReferenceExceptions somewhere in IText source, "the document is not open", etc...
For example, this will throw no error but the resulting pdf will only contain the attachments but not the html email body:
Document document = new Document();
StringReader sr = new StringReader(mail.Body);
HTMLWorker htmlparser = new HTMLWorker(document);
using (FileStream fs = new FileStream(targetPath, FileMode.Create))
{
PdfCopy writer = new PdfCopy(document, fs);
document.Open();
htmlparser.Parse(sr);
foreach (string fileName in pdfList)
{
PdfReader reader = new PdfReader(fileName);
reader.ConsolidateNamedDestinations();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
writer.AddPage(page);
}
PRAcroForm form = reader.AcroForm;
if (form != null)
{
writer.CopyAcroForm(reader);
}
reader.Close();
}
writer.Close();
document.Close();
}
I'm using the LGPL licensed ITextSharp 4.1.6
From v4.1.6 fanboy to v4.1.6 fanboy :D
Looks like the HTMLWorker is closing the documents stream right after parsing. So as a workaround, you could create a pdf from your mailbody in memory. And then add this one together with the attachment to your final pdf.
Here is some code, that should do the trick:
StringReader htmlStringReader = new StringReader("<html><body>Hello World!!!!!!</body></html>");
byte[] htmlResult;
using (MemoryStream htmlStream = new MemoryStream())
{
Document htmlDoc = new Document();
PdfWriter htmlWriter = PdfWriter.GetInstance(htmlDoc, htmlStream);
htmlDoc.Open();
HTMLWorker htmlWorker = new HTMLWorker(htmlDoc);
htmlWorker.Parse(htmlStringReader);
htmlDoc.Close();
htmlResult = htmlStream.ToArray();
}
byte[] pdfResult;
using (MemoryStream pdfStream = new MemoryStream())
{
Document doc = new Document();
PdfCopy copyWriter = new PdfCopy(doc, pdfStream);
doc.Open();
PdfReader htmlPdfReader = new PdfReader(htmlResult);
AppendPdf(copyWriter, htmlPdfReader); // your foreach pdf code here
htmlPdfReader.Close();
PdfReader attachmentReader = new PdfReader("C:\\temp\\test.pdf");
AppendPdf(copyWriter, attachmentReader);
attachmentReader.Close();
doc.Close();
pdfResult = pdfStream.ToArray();
}
using (FileStream fs = new FileStream("C:\\temp\\test2.pdf", FileMode.Create, FileAccess.Write))
{
fs.Write(pdfResult, 0, pdfResult.Length);
}
private void AppendPdf(PdfCopy writer, PdfReader reader)
{
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
writer.AddPage(page);
}
}
Ofc you could directly use a FileStream for the final document instead of a MemoryStream as well.

Merging PDF with ITextSharp takes time

I am using ITextSharp to merge PDFs.
My problem is when I merge huge PDFs, it takes a very long time to do it (many minutes). It appears that it takes all this time on the "document.close()".
Here is my code :
iTextSharp.text.Document doc = new iTextSharp.text.Document();
PdfCopy copy = new PdfCopy(doc, msOutput);
copy.SetMergeFields();
doc.Open();
byte[] byteArray = Convert.FromBase64String("someString");
PdfReader reader = new PdfReader(byteArray);
copy.AddDocument(reader);
doc.Close(); // <== It takes time here !
byte[] form = msOutput.ToArray();
Is there anything I did wrong ?
How can I improve this merging time ?
You are missing some Close() calls - this may help to bring your time down:
byte[] form
using (var msOutput = new MemoryStream())
{
iTextSharp.text.Document doc = new iTextSharp.text.Document();
byte[] byteArray = Convert.FromBase64String("someString");
PdfCopy copy = new PdfCopy(doc, msOutput);
copy.SetMergeFields();
doc.Open();
PdfReader reader = new PdfReader(byteArray);
copy.AddDocument(reader);
reader.Close();
copy.Close();
doc.Close();
form = msOutput.ToArray();
}
You should also be sure you are properly disposing of your stream after use.

Copying PDF without loose form field structure with ItextSharp

I would like to get a pdf, keep somes pages, then save it to another destination without losing fieldstructure.
Here the code perfectly working for copying:
string sourceFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string sourceFile = Path.Combine(sourceFolder, "POMultiple.pdf");
string fileName = #"C:\Users\MyUser\Desktop\POMultiple.pdf";
byte[] file = System.IO.File.ReadAllBytes(fileName);
public static void removePagesFromPdf(byte[] sourceFile, String destinationFile, params int[] pagesToKeep)
{
//Used to pull individual pages from our source
PdfReader r = new PdfReader(sourceFile);
//Create our destination file
using (FileStream fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (Document doc = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
//Open the desitination for writing
doc.Open();
//Loop through each page that we want to keep
foreach (int page in pagesToKeep)
{
//Add a new blank page to destination document
doc.NewPage();
//Extract the given page from our reader and add it directly to the destination PDF
writer.DirectContent.AddTemplate(writer.GetImportedPage(r, page), 0, 0);
}
//Close our document
doc.Close();
}
}
}
But when I open "TestOutput.pdf" file in acrobat reader all my fields are empty.
Any Help ?
You need something like this:
PdfReader reader = new PdfReader(sourceFile);
reader.SelectPages(2-4,8-9);
PdfStamper stp = new PdfStamper(reader, new FileStream(destinationFile, FileMode.Create));
stp.Close();
reader.Close();

Categories