How do you convert an RTF file to a PDF file using iTextSharp - itext

I have searched and I could not find an answer. For example, this doesn't work. My port:
static byte[] RtfToPdf(string rtf)
{
byte[] pdf = null;
using (var inputStream = GenerateStreamFromString(rtf))
using (var outputStream = new MemoryStream())
{
var pdfDocument = new iTextSharpDocument();
var pdfWriter = PdfWriter.GetInstance(pdfDocument, outputStream);
pdfDocument.Open();
RtfParser rtfParser = new RtfParser(null);
rtfParser.ConvertRtfDocument(inputStream, pdfDocument);
pdfDocument.Close();
pdfWriter.Close();
pdf = outputStream.ToArray();
}
return pdf;
}
public static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.UTF8.GetBytes(value));
}
That simply copies the text of the RTF to a PDF without any of the formatting that was in the RTF. I am using iTextSharp-LGPL which is version 4.1.6 of iTextSharp.
I personally can't find any useful documentation. iText itself isn't intuitive so I'm having a hard time even guessing about what to try.

Related

itext7 + pdfHtml: how set portrait orientation and fit content on ConvertToPdf

I did a simple html to pdf conversion getting a landscape orientation.
In the pdfHtml release notes I see that the default orientation should be portrait but I got a landscape.
I'm not able to find the option/parameter/setting to do it.
Probably it is in the ConverterProperties object hidden to my eyes :-(
Any suggestion?
Here is my very simple code
public byte[] HtmlToPdf(string html)
{
using (Stream htmlSource = new MemoryStream(Encoding.UTF8.GetBytes(html)))
using (MemoryStream pdfDest = new MemoryStream())
{
ConverterProperties converterProperties = new ConverterProperties();
HtmlConverter.ConvertToPdf(htmlSource, pdfDest, converterProperties);
return pdfDest.ToArray();
}
}
EDIT after answers (I got the right orientation!):
Now I have to find a way to scale down the content in order to fit the content and have the right margins without cutting the image.
public static byte[] HtmlToPdf(string html)
{
using (Stream htmlSource = new MemoryStream(Encoding.UTF8.GetBytes(html)))
using (MemoryStream pdfDest = new MemoryStream())
{
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(pdfDest));
pdfDocument.SetDefaultPageSize(PageSize.A4.Rotate());
ConverterProperties converterProperties = new ConverterProperties();
HtmlConverter.ConvertToPdf(htmlSource, pdfDocument, converterProperties);
return pdfDest.ToArray();
}
}
HTML result:
PDF result:
I solved changing the library from itext7 to DinkToPdf. I found it very simple to use and enough to my needs.
The MVC controller after changing the library to DinkToPdf
public byte[] PdfCreatorController(IConverter converter)
string html = await reader.ReadToEndAsync();
var globalSettings = new GlobalSettings
{
ColorMode = ColorMode.Color,
Orientation = Orientation.Portrait,
PaperSize = PaperKind.A4,
Margins = new MarginSettings { Top = 10 },
DocumentTitle = "Report",
Out = string.Empty,
};
var objectSettings = new ObjectSettings
{
PagesCount = true,
HtmlContent = html,
WebSettings = { DefaultEncoding = "utf-8", UserStyleSheet = Path.Combine(Directory.GetCurrentDirectory(), "assets", "styles.css") },
};
var pdf = new HtmlToPdfDocument()
{
GlobalSettings = globalSettings,
Objects = { objectSettings }
};
return = _converter.Convert(pdf);
}
PDF Result

Set the iText 7 page size based on the HTML content

I have the following Java program to create an iText PDF:
//Create the PDF file
public int CreatePDF(String[] pSrc,
String pDest)
throws IOException
{
//Initialize
ConverterProperties vProperties = new ConverterProperties();
//Adding the fonts
FontProvider vfontProvider = new DefaultFontProvider(false, false, false);
for (String font : FONTS)
{
FontProgram vfontProgram = FontProgramFactory.createFont(font);
vfontProvider.addFont(vfontProgram);
}
vProperties.setFontProvider(vfontProvider);
PdfWriter vWriter = new PdfWriter(pDest, new WriterProperties().setCompressionLevel(9));
PdfDocument vPDF = new PdfDocument(vWriter);
PdfMerger vMerger = new PdfMerger(vPDF);
//Convert to PDF
for (String vHTML : pSrc)
{
ByteArrayOutputStream vArrByteAOS = new ByteArrayOutputStream();
PdfDocument vDoc = new PdfDocument(new PdfWriter(vArrByteAOS, new WriterProperties().setCompressionLevel(9)));
vDoc.setDefaultPageSize(new PageSize(735, 1080));
HtmlConverter.convertToPdf(vHTML, vDoc, vProperties);
vDoc = new PdfDocument(new PdfReader(new ByteArrayInputStream(vArrByteAOS.toByteArray())));
vMerger.merge(vDoc, 1, vDoc.getNumberOfPages());
vDoc.close();
}
vPDF.close();
return 0;
}
How can I set the Page Height (now hardcoded to 1080) based on the size of the HTML content (pSrc) in order to ensure that it fits to one page.

How do I merge two PDF files with attachments using itext?

I am trying to merge two pdf files (file1.pdf and file2.pdf) into a single file file3.pdf. One of the source files, file2.pdf has few attachments.
Using PdfCopyFields addDocument method does not include the attachments in the source pdf files to the destination pdf file. How do I achieve this?
Extracting the document level attachments from source files using PdfDictionary and adding them to the destination file using PdfWriter addFileAttachment method works.
Can you please let me know if there is any other efficient method to include the attachments from source pdf files to be included in destination pdf file after merging?
This is the sample code that I am using to replicate the scenario.
public class TestItext
{
public String[] attachments;
public TestItext()
{
attachments = new String[2];
}
public static void main(String[] args)
{
try
{
TestItext obj = new TestItext();
obj.extractDocLevelAttachments("C:\\source.pdf");
obj.addAttachments("C:\\source.pdf","C:\\temp\\dest.pdf");
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void extractDocLevelAttachments(String filename) throws IOException
{
PdfReader reader = new PdfReader(filename);
PdfDictionary root = reader.getCatalog();
PdfDictionary documentnames = root.getAsDict(PdfName.NAMES);
PdfDictionary embeddedfiles = documentnames.getAsDict(PdfName.EMBEDDEDFILES);
PdfArray filespecs = embeddedfiles.getAsArray(PdfName.NAMES);
PdfDictionary filespec;
PdfDictionary refs;
FileOutputStream fos;
PRStream stream;
int count = 0;
for (int i = 0; i < filespecs.size(); ) {
filespecs.getAsString(i++);
filespec = filespecs.getAsDict(i++);
refs = filespec.getAsDict(PdfName.EF);
for (Object key : refs.getKeys()) {
fos = new FileOutputStream(String.format("C:\\temp\\"+ filespec.getAsString((PdfName)key).toString()));
attachments[count++] = String.format("C:\\temp\\"+ filespec.getAsString((PdfName)key).toString());
stream = (PRStream) PdfReader.getPdfObject(refs.getAsIndirectObject((PdfName)key));
fos.write(PdfReader.getStreamBytes(stream));
fos.flush();
fos.close();
}
}
reader.close();
}
public void addAttachments(String src, String dest) throws IOException, DocumentException
{
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
for (int i = 0; i < attachments.length; i++) {
addAttachment(stamper.getWriter(), new File(attachments[i]));
}
stamper.close();
}
protected void addAttachment(PdfWriter writer, File src) throws IOException {
PdfFileSpecification fs =
PdfFileSpecification.fileEmbedded(writer, src.getAbsolutePath(), src.getName(), null);
writer.addFileAttachment(src.getName().substring(0, src.getName().indexOf('.')), fs);
}
}

Serializing XML Document through application domains

I'm trying to serialize an XML file between two software components, with a client-server fashioned code.
First of all, i'll show how i solved the same issue for Bitmaps (code has been simplified for writting this):
Initially, this code serializes me Bitmaps at the server side:
public String ImageToString(Bitmap img)
{
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
}
return Convert.ToBase64String(byteArray);
}
And this deserializes the Bitmap at the client side:
public Bitmap StringToImage(string imageString)
{
byte[] array = Convert.FromBase64String(imageString);
Bitmap image = (Bitmap)Bitmap.FromStream(new MemoryStream(array));
return image;
}
What i really want to do now is do the same, but with XML files. I have at the server side:
public XmlDocument RemoteXMLfile()
{
XmlDocument doc = new XmlDocument();
doc.Load("myXMLFile.xml");
return doc;
}
But this makes the compiler to complain because it finds the XML document unmarked as serializable.
My question is: how do i solve this? Thanks!
I answer my own question:
The XMLDocuments is loaded and converted to a byte array at the server side:
public byte[] RemoteXMLfile()
{
XmlDocument doc = new XmlDocument();
doc.Load("myLocalXMLfile.xml");
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
doc.Save(stream);
stream.Close();
byteArray = stream.ToArray();
}
return byteArray;
}
And at the client side, we convert again to an XML document from its byte array shape:
byte[] docbytearray = RemoteXMLfile();
XmlDocument doc = new XmlDocument();
MemoryStream ms = new MemoryStream(docbytearray);
doc.Load(ms);

iTextSharp - Create new document as Byte[]

Have a little method which goes to the database and retrieves a pdf document from a varbinary column and then adds data to it. I would like to add code so that if this document (company stationery ) is not found then a new blank document is created and returned. The method could either return a Byte[] or a Stream.
Problem is that the variable "bytes" in the else clause is null.
Any ideas what's wrong?
private Byte[] GetBasePDF(Int32 AttachmentID)
{
Byte[] bytes = null;
DataTable dt = ServiceFactory
.GetService().Attachments_Get(AttachmentID, null, null);
if (dt != null && dt.Rows.Count > 0)
{
bytes = (Byte[])dt.Rows[0]["Data"];
}
else
{
// Create a new blank PDF document and return it as Byte[]
ITST.Document doc =
new ITST.Document(ITST.PageSize.A4, 50f, 50f, 25f, 25f);
MemoryStream ms = new MemoryStream();
PdfCopy copy = new PdfCopy(doc, ms);
ms.Position = 0;
bytes = ms.ToArray();
}
return bytes;
}
You are trying to use PdfCopy but that's intended for existing documents, not new ones. You just need to create a "blank" document using PdfWriter and Document. iText won't let you create a 100% empty document but the code below essentially does that by just adding a space.
private static Byte[] CreateEmptyDocument() {
using (var ms = new System.IO.MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.Add(new Paragraph(" "));
doc.Close();
}
}
return ms.ToArray();
}
}
I think you may need to use
bytes = ms.GetBuffer();
not
bytes = ms.ToArray();