Converting dynamic cshtml to pdf using iTextSharp? - asp.net-mvc-4

I was using Rotativa for the conversion of html to pdf. My whole aim was to send receipt as pdf to customers emailid. It was working well locally but when deployed in GoDaddy Server its not supported. So I am planning to generate the pdf using iTextSharp(Viewers Opinion is also invited).
Code written for the generation of pdf in Rotativa:
public ActionResult GetPdfReceipt(int RegId)
{
var actionPDF = new Rotativa.ActionAsPdf("GetPdfReceipt", new { RegId = regId })
{
FileName = "Receipt.pdf"
};
//Dynamic student receipt pdf
var byteArrayDynamic = actionPDF.BuildPdf(ControllerContext);
}
public ActionResult GetPdfReceipt(int RegId)
{
try
{
var _mdlReceiptPdf = new ReceiptPdfVM
{
...
...
};
return View("Receipts", _mdlReceiptPdf);
}
catch (Exception ex)
{
return View("");
}
}
I have gone through some of the codes for generating pdf using iTextSharp and it was as follows
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.Charset = "";
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=LoginReportPerDay.pdf");
StringWriter sWriter = new StringWriter();
HtmlTextWriter hTWriter = new HtmlTextWriter(sWriter);
GridView1.RenderControl(hTWriter);
StringReader sReader = new StringReader(sWriter.ToString());
Document pdf = new Document(PageSize.A4);
HTMLWorker worker = new HTMLWorker(pdf);
PdfWriter.GetInstance(pdf, HttpContext.Current.Response.OutputStream);
pdf.Open();
worker.Parse(sReader);
pdf.Close();
HttpContext.Current.Response.Write(pdf);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
How can I use the above code to render dynamically generated Receipt View pdf array bytes.

Related

Fill XFA without breaking usage rights

I have an XFA form that I can successfully fill in by extracting the XML modifying and writing back. Works great if you have the full Adobe Acrobat, but fails with Adobe Reader. I have seen various questions on the same thing with answers but they were some time ago so updating an XFA that is readable by Adobe Reader may no longer be doable?
I use this code below and I've utilised the StampingProperties of append as in the iText example but still failing. I'm using iText 7.1.15.
//open file and write to temp one
PdfDocument pdf = new(new PdfReader(FileToProcess), new PdfWriter(NewPDF), new StampingProperties().UseAppendMode());
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
XfaForm xfa = form.GetXfaForm();
XElement node = xfa.GetDatasetsNode();
IEnumerable<XNode> list = node.Nodes();
foreach (XNode item in list)
{
if (item is XElement element && "data".Equals(element.Name.LocalName))
{
node = element;
break;
}
}
XmlWriterSettings settings = new() { Indent = true };
using XmlWriter writer = XmlWriter.Create(XMLOutput, settings);
{
node.WriteTo(writer);
writer.Flush();
writer.Close();
}
//We now how to strip an extra xfa line if updating
if(update)
{
string TempXML= CSTrackerHelper.MakePath($"{AppContext.BaseDirectory}Temp", $"{Guid.NewGuid()}.XML");
StreamReader fsin = new(XMLOutput);
StreamWriter fsout = new(TempXML);
string linedata = string.Empty;
int cnt = 0;
while (!fsin.EndOfStream)
{
if (cnt != 3 && linedata != string.Empty)
{
fsout.WriteLine(linedata);
}
linedata = fsin.ReadLine();
cnt++;
}
fsout.Close();
fsin.Close();
XMLOutput = TempXML;
}
xlogger.Info("Populating pdf fields");
//Now loop through our field data and update the XML
XmlDocument xmldoc = new();
xmldoc.Load(XMLOutput);
XmlNamespaceManager xmlnsManager = new(xmldoc.NameTable);
xmlnsManager.AddNamespace("xfa", #"http://www.xfa.org/schema/xfa-data/1.0/");
string[] FieldValues;
string[] MultiNodes;
foreach (KeyValuePair<string, DocumentFieldData> v in DocumentData.FieldData)
{
if (!string.IsNullOrEmpty(v.Value.Field))
{
FieldValues = v.Value.Field.Contains(";") ? v.Value.Field.Split(';') : (new string[] { v.Value.Field });
foreach (string FValue in FieldValues)
{
XmlNodeList aNodes;
if (FValue.Contains("{"))
{
aNodes = xmldoc.SelectNodes(FValue.Substring(0, FValue.LastIndexOf("{")), xmlnsManager);
if (aNodes.Count > 1)
{
//We have a multinode
MultiNodes = FValue.Split('{');
int NodeIndex = int.Parse(MultiNodes[1].Replace("}", ""));
aNodes[NodeIndex].InnerText = v.Value.Data;
}
}
else
{
aNodes = xmldoc.SelectNodes(FValue, xmlnsManager);
if (aNodes.Count >= 1)
{
aNodes[0].InnerText = v.Value.Data;
}
}
}
}
}
xmldoc.Save(XMLOutput);
//Now we've updated the XML apply it to the pdf
xfa.FillXfaForm(new FileStream(XMLOutput, FileMode.Open, FileAccess.Read));
xfa.Write(pdf);
pdf.Close();
FYI I've also tried to set a field directly also with the same results.
PdfReader preader = new PdfReader(source);
PdfDocument pdfDoc=new PdfDocument(preader, new PdfWriter(dest), new StampingProperties().UseAppendMode());
PdfAcroForm pdfForm = PdfAcroForm.GetAcroForm(pdfDoc, true);
XfaForm xform = pdfForm.GetXfaForm();
xform.SetXfaFieldValue("VRM[0].CoverPage[0].Wrap2[0].Table[0].CSID[0]", "Test");
xform.Write(pdfForm);
pdfDoc.Close();
If anyone has any ideas it would be appreciated.
Cheers
I ran into a very similar issue. I was attempting to auto fill an XFA that was password protected while not breaking the certificate or usage rights (it allowed filling). iText7 seems to have made this not possible for legal/practical reasons, however it is still very much possible with iText5. I wrote the following working codeusing iTextSharp (C# version if iText5):
using iTextSharp.text;
using iTextSharp.text.pdf;
string pathToRead = "/Users/home/Desktop/c#pdfParser/encrypted_empty.pdf";
string pathToSave = "/Users/home/Desktop/c#pdfParser/xfa_encrypted_filled.pdf";
string data = "/Users/home/Desktop/c#pdfParser/sample_data.xml";
FillByItextSharp5(pathToRead, pathToSave, data);
static void FillByItextSharp5(string pathToRead, string pathToSave, string data)
{
using (FileStream pdf = new FileStream(pathToRead, FileMode.Open))
using (FileStream xml = new FileStream(data, FileMode.Open))
using (FileStream filledPdf = new FileStream(pathToSave, FileMode.Create))
{
PdfReader.unethicalreading = true;
PdfReader pdfReader = new PdfReader(pdf);
PdfStamper stamper = new PdfStamper(pdfReader, filledPdf, '\0', true);
stamper.AcroFields.Xfa.FillXfaForm(xml, true);
stamper.Close();
pdfReader.Close();
}
}
PdfStamper stamper = new PdfStamper(pdfReader, filledPdf, '\0', true)
you have to use this line.

Support to convert the HTML to PDF in Xamarin Forms

With the reference of following StackOverflow suggestion,
Convert HTML to PDF in .NET
I tried to convert the HTML file to PDF using HtmlRenderer.PdfSharp but unfortunately it shows compatible error like below,
HtmlRendererCore.PdfSharpCore 1.0.1 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package HtmlRendererCore.PdfSharpCore 1.0.1 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
HtmlRenderer.Core 1.5.0.5 is not compatible with monoandroid90 (MonoAndroid,Version=v9.0). Package HtmlRenderer.Core 1.5.0.5 supports:
- net20 (.NETFramework,Version=v2.0)
- net30 (.NETFramework,Version=v3.0)
- net35-client (.NETFramework,Version=v3.5,Profile=Client)
- net40-client (.NETFramework,Version=v4.0,Profile=Client)
- net45 (.NETFramework,Version=v4.5)
HtmlRendererCore.PdfSharpCore 1.0.1 is not compatible with monoandroid90 (MonoAndroid,Version=v9.0). Package HtmlRendererCore.PdfSharpCore 1.0.1 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
And I tried with wkhtmltopdf too but it throws similar error in android and other platform projects.
My requirement is to convert the HTML file to PDF file only (no need to view the PDF file, just to save it in local path).
Can anyone please provide suggestions?
Note : Need open source suggestion :)
Awaiting for your suggestions !!!
Support to convert the HTML to PDF in Xamarin Forms
You can read the HTML as a stream and store it into local like below,
public static class FileManager
{
public static async Task<MemoryStream> DownloadFileAsStreamAsync(string url)
{
try
{
var stream = new MemoryStream();
using (var httpClient = new HttpClient())
{
var downloadStream = await httpClient.GetStreamAsync(new Uri(url));
if (downloadStream != null)
{
await downloadStream.CopyToAsync(stream);
}
}
return stream;
}
catch (Exception exception)
{
return null;
}
}
public static async Task<bool> DownloadAndWriteIntoNewFile(string url, string fileName)
{
var stream = await DownloadFileAsStreamAsync(url);
if (stream == null || stream.Length == 0)
return false;
var filePath = GetFilePath(fileName);
if (!File.Exists(filePath))
return false;
File.Delete(filePath);
// Create file.
using (var createdFile = File.Create(filePath))
{
}
// Open and write into file.
using (var openFile = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite))
{
stream.WriteTo(openFile);
}
return true;
}
public static string GetFilePath(string fileName)
{
var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), fileName);
return filePath;
}
public static void WriteAsText(string filePath, string contents)
{
File.WriteAllText(filePath, contents);
}
public static string ReadAsText(string filePath)
{
return File.ReadAllText(filePath);
}
}
You can read a stored pdf file and displayed using webview like below,
private async void HtmlToPDF()
{
await FileManager.DownloadAndWriteIntoNewFile("https://www.google.co.in/?gws_rd=ssl", "SavePDF.pdf");
var filePath = FileManager.GetFilePath("SavePDF.pdf");
var pdfString = FileManager.ReadAsText(filePath);
var webView = new WebView
{
Source = new HtmlWebViewSource
{
Html = pdfString
}
};
this.Content = webView;
}
And the output below,
Likewise, you can save HTML as PDF and do what you want..
you can use the HtmlToPdfConverter
private void ConvertUrlToPdf()
{
try {
String serverIPAddress = serverIP.Text;
uint serverPortNumber = uint.Parse (serverPort.Text);
// create the HTML to PDF converter object
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter (serverIPAddress, serverPortNumber);
// set service password if necessary
if (serverPassword.Text.Length > 0)
htmlToPdfConverter.ServicePassword = serverPassword.Text;
// set PDF page size
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
// set PDF page orientation
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
// convert the HTML page from given URL to PDF in a buffer
byte[] pdfBytes = htmlToPdfConverter.ConvertUrl (urlToConvert.Text);
string documentsFolder = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
string outPdfFile = System.IO.Path.Combine (documentsFolder, "EvoHtmlToPdf.pdf");
// write the PDF buffer in output file
System.IO.File.WriteAllBytes (outPdfFile, pdfBytes);
// open the PDF document in the default PDF viewer
UIDocumentInteractionController pdfViewer = UIDocumentInteractionController.FromUrl (Foundation.NSUrl.FromFilename (outPdfFile));
pdfViewer.PresentOpenInMenu (this.View.Frame, this.View, true);
} catch (Exception ex) {
UIAlertView alert = new UIAlertView ();
alert.Title = "Error";
alert.AddButton ("OK");
alert.Message = ex.Message;
alert.Show ();
}
}
another
you can see thisurl

iTextSharp Html Arabic Mixed Content to PDF

We are in project for educational domain, where we are looking for importing Arabic content, Images (uri/base64 crypted texts), html tables.
We are facing issue while executing using HtmlWorker with Stream data. It throws error as "the document has no pages"
string str="html content contains arabic font texts/images";
using (MemoryStream ms = new MemoryStream())
{
using (iTextSharp.text.Document document = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 25, 25, 30, 30))
{
using (iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document,ms))
{
using (var htmlWorker = new iTextSharp.text.html.simpleparser.HTMLWorker(document))
{
//HTMLWorker doesn't read a string directly but instead needs a TextReader (which StringReader subclasses)
using (var sr = new StreamReader(str)) /// We are facing issue at this juncture where it throws error.
{
//Parse the HTML
htmlWorker.Parse(sr);
}
}
document.Close();
writer.Close();
ms.Close();
Response.ContentType = "pdf/application";
Response.AddHeader("content-disposition", "attachment;filename=First_PDF_document.pdf");
Response.OutputStream.Write(ms.ToArray(), 0, ms.ToArray().Length);
}
}
}
Could you please help us regarding this?
Now,
I have tried with other approach:
using (var htmlWorker = new iTextSharp.text.html.simpleparser.HTMLWorker(document))
{
using (Stream s = GenerateStreamFromString(str))
{
using (var srt = new StreamReader(s))
{
//Parse the HTML
htmlWorker.Parse(srt); //this line throws error now.
}
}
}
public Stream GenerateStreamFromString(string s)
{
MemoryStream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
Error message:
"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters."

Html to pdf some characters are missing (itextsharp) in Asp.Net MVC Application

I want to export razor view to pdf by using the itextsharp library. The problem is that some turkish characters such as İ,ı,Ş,ş etc... are missing in the pdf document. The code used to export the pdf is:
public PdfActionResult(object model)
{
Model = model;
}
public override void ExecuteResult(ControllerContext context)
{
IView viewEngineResult;
ViewContext viewContext;
if (ViewName == null)
{
ViewName = context.RouteData.GetRequiredString("action");
}
context.Controller.ViewData.Model = Model;
var workStream = new MemoryStream();
var document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, workStream);
writer.CloseStream = false;
document.Open();
viewEngineResult = ViewEngines.Engines.FindView(context, ViewName, null).View;
var sb = new StringBuilder();
TextWriter tr = new StringWriter(sb);
viewContext = new ViewContext(context, viewEngineResult, context.Controller.ViewData,
context.Controller.TempData, tr);
viewEngineResult.Render(viewContext, tr);
CultureInfo ci = new CultureInfo("az-Latn-AZ");
Encoding enc = Encoding.GetEncoding(ci.TextInfo.ANSICodePage);
Stream stream = new MemoryStream(enc.GetBytes(sb.ToString()));
XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, stream, null);
document.Close();
new FileContentResult(workStream.ToArray(), "application/pdf").ExecuteResult(context);
}
}
Then I access it as:
public ActionResult StudentPdf(Guid studentId)
{
var model = _studentRepository.GetByIdGuid(studentId);
return new PdfActionResult(model);
}
Thanks for reply
by this way you can print all turkish character.
String htmlText = html.ToString();
Document document = new Document();
string filePath = HostingEnvironment.MapPath("~/Content/Pdf/");
PdfWriter.GetInstance(document, new FileStream(filePath + "\\pdf-"+Name+".pdf", FileMode.Create));
document.Open();
iTextSharp.text.html.simpleparser.HTMLWorker hw = new iTextSharp.text.html.simpleparser.HTMLWorker(document);
FontFactory.Register(Path.Combine(_webHelper.MapPath("~/App_Data/Pdf/arial.ttf")), "Garamond"); // 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");
hw.SetStyleSheet(css);
hw.Parse(new StringReader(htmlText));
Hope this helps
Regards,
Vinit Patel

How to merge PDFs into a PDF Portfolio?

I am looking for the functionality that creates PDF Portfolios:
The image shows the free adobe reader that can be downloaded from Adobe (duh!). When I open this particular PDF, I was surprised that it has all these Layout, Files and Attachment features. It is definitely not the normal "PDF merge". It is more like a package with multiple PDFs.
Can itextsharp do this? What is the search term for this PDF functionality?
The term you're looking for is PDF Portfolios. You can create PDFs like this with iTextSharp. Here are a couple of C# examples from the iText book:
Chapter16 - KubrickCollection
Chapter16 - KubrickMovies
If you choose to download the KubrickMovies result file, change the extension to ".pdf". Just noticed it now - will try and fix the error this weekend.
To generate pdf portfolio (using iTextSharp) first we need to create a collection, then store it.
Example read one pdf file, create from it a collection of 2 files hello.pdf,united_states.pdf finally store as Test.pdf
static void Main(string[] args)
{
Document pdfDoc = null;
FileStream fstr = null;
try
{
pdfDoc = new Document(PageSize.A4);
fstr = new FileStream("Test.pdf", FileMode.Create);
var pdfWriter = PdfWriter.GetInstance(pdfDoc, fstr);
pdfDoc.Open();
pdfDoc.Add(new Chunk());
PdfCollection collection = new PdfCollection(PdfCollection.TILE);
var filePath = #"somePDF.pdf";
var fileInfo = new FileInfo(filePath);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(PdfName.Moddate, new PdfDate(fileInfo.LastWriteTime));
pdfWriter.Collection = collection;
PdfFileSpecification fileSpec = PdfFileSpecification.FileEmbedded(
pdfWriter,
filePath,
fileInfo.Name,
null
);
pdfWriter.AddFileAttachment("united_states.pdf", fileSpec);
fileSpec = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null);
pdfWriter.AddFileAttachment("hello.pdf", fileSpec);
pdfDoc.Close();
}
finally
{
pdfDoc.Close();
pdfDoc = null;
fstr.Close();
}
}
Here is the simple sample to show how we can attach files to a new PDF file:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace PDFAttachment
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();
pdfDoc.Add(new Phrase("Test"));
var filePath = #"C:\path\logo.png";
var fileInfo = new FileInfo(filePath);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(PdfName.MODDATE, new PdfDate(fileInfo.LastWriteTime));
var fs = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null, true, null, pdfDictionary);
pdfWriter.AddFileAttachment("desc.", fs);
}
Process.Start("Test.pdf");
}
}
}
Or to an existing PDF file:
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace PDFAttachment
{
class Program
{
static void Main(string[] args)
{
var reader = new PdfReader("Test.pdf");
using (var stamper = new PdfStamper(reader, new FileStream("newTest.pdf", FileMode.Create)))
{
var filePath = #"C:\path\logo.png";
addAttachment(stamper, filePath, "desc.");
stamper.Close();
}
Process.Start("newTest.pdf");
}
private static void addAttachment(PdfStamper stamper, string filePath, string description)
{
var fileInfo = new FileInfo(filePath);
var pdfDictionary = new PdfDictionary();
pdfDictionary.Put(PdfName.MODDATE, new PdfDate(fileInfo.LastWriteTime));
var pdfWriter = stamper.Writer;
var fs = PdfFileSpecification.FileEmbedded(pdfWriter, filePath, fileInfo.Name, null, true, null, pdfDictionary);
stamper.AddFileAttachment(description, fs);
}
}
}