I have uploaded documents (only image format) to mysql database through c#. This entry in the database table will have reference Id for each transaction. Upon clicking on download button, all uploaded images of respective table id should merge into a single pdf file. How can I Achieve this?. Require C# code to download
Below is the sample code which is not working. It returns system.byte[] as response
[HttpPost]
public static byte[] MergeFile()
{
PdfReader.unethicalreading = true;
using (iTextSharp.text.Document doc = new iTextSharp.text.Document())
{
doc.SetPageSize(PageSize.A4);
using (var ms = new MemoryStream())
{
// PdfWriter wri = PdfWriter.GetInstance(doc, ms);
using (PdfCopy pdf = new `enter code here`PdfCopy(doc, ms))
{
doc.Open();
using (MySqlConnection connection = new MySqlConnection(ConfigurationManager.ConnectionStrings[2].ConnectionString))
{
using (MyDBContext context = new MyDBContext(connection, false))
{
try
{
var getDocs = context.Document.Where(p => p.ReferenceId == 1).ToList();
foreach (DAL.Document info in getDocs)
{
try
{
doc.NewPage();
iTextSharp.text.Document imageDocument = null;
PdfWriter imageDocumentWriter = null;
switch (info.Extension.Trim('.').ToLower())
{
case "image/png":
using (imageDocument = new iTextSharp.text.Document())
{
using (var imageMS = new MemoryStream())
{
using (imageDocumentWriter = PdfWriter.GetInstance(imageDocument, imageMS))
{
imageDocument.Open();
if (imageDocument.NewPage())
{
var image = iTextSharp.text.Image.GetInstance(info.Documents);
image.Alignment = Element.ALIGN_CENTER;
image.ScaleToFit(doc.PageSize.Width - 10, doc.PageSize.Height - 10);
if (!imageDocument.Add(image))
{
throw new Exception("Unable to add image to page!");
}
imageDocument.Close();
imageDocumentWriter.Close();
using (PdfReader imageDocumentReader = new PdfReader(imageMS.ToArray()))
{
var page = pdf.GetImportedPage(imageDocumentReader, 1);
pdf.AddPage(page);
imageDocumentReader.Close();
}
}
}
}
}
break;
}
catch (Exception e)
{
e.Data["FileName"]=info.DocumentName;
throw e;
}
}
}
catch (Exception e)
{
var k = e.Message;
}
}
}
}
if (doc.IsOpen()) doc.Close();
return ms.ToArray();
}
}
}
Related
I want convert HTML to PDF by using iTextSharp, work success for English characters but when using Unicode characters PDF convert but dose not display Unicode characters
This answer not help me
Thanks for help :)
My Code
public ActionResult Export()
{
Byte[] bytes;
using (var ms = new MemoryStream())
{
using (var doc = new Document())
{
using (var writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
var example_html = #"<p> سڵاو</p>";
var example_css = #".headline{font-size:200%}";
using (var htmlWorker = new iTextSharp.text.html.simpleparser.HTMLWorker(doc))
{
using (var sr = new StringReader(example_html))
{
htmlWorker.Parse(sr);
}
}
using (var srHtml = new StringReader(example_html))
{
iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
}
using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css)))
{
using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html)))
{
iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss, System.Text.Encoding.UTF8);
}
}
doc.Close();
}
}
bytes = ms.ToArray();
}
return File(bytes, "application/pdf", "test.pdf");
}
Alternative a Way
I try use Rotativa it's easy to use, and it follow the same architecture of MVC
PM > Install-Package Rotativa.MVC -Version 2.0.3
USE
try
{
return new ActionAsPdf("Contact"); // this view or html for convert PDF
}
catch (Exception e)
{
return RedirectToAction("GeneralError", "Error");
}
Basically, i have original XFA file with many Custom > Properties and i can convert it to PDF-A but all of properties have lost after convert.
Here is my ConvertToPDFa Code:
public byte[] ConvertToPDFa3(byte[] OriginPDF,byte[] FileStore,string XML)
{
//***************************************
// Convert PDF to PDFa3 and Attach XML .
//***************************************
//Create Reader for Reading PDF in byte[]
using (var reader = new PdfReader(OriginPDF))
{
// Open Stream for Converting
using (var Convertstream = new MemoryStream())
{
// New Doc for PDF/A-3
Document pdfAdocument = new Document();
//Init instance for pdfAdocument
PdfAWriter writer = PdfAWriter.GetInstance(pdfAdocument, Convertstream, PdfAConformanceLevel.PDF_A_3U);
writer.CreateXmpMetadata();
if (!pdfAdocument.IsOpen())
pdfAdocument.Open();
PdfContentByte cb = writer.DirectContent; // Holds the PDF data
//Count original PDF pages and uses for pdfa-3
PdfImportedPage page;
int pageCount = reader.NumberOfPages;
for (int i = 0; i < pageCount; i++)
{
pdfAdocument.NewPage();
page = writer.GetImportedPage(reader, i + 1);
cb.AddTemplate(page, 0, 0);
}
//Create Output Intents
ICC_Profile icc = ICC_Profile.GetInstance(AppDomain.CurrentDomain.BaseDirectory + "res\\sRGB Color Space Profile.icm");
writer.SetOutputIntents("sRGB IEC61966-2.1", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
//Embedded File to PDFa3
writer.AddFileAttachment("XML for : " + certRefNumber, FileStore, XML, lblRefNo.Text + ".xml");
//Close all file to finish
pdfAdocument.Close();
reader.Close();
//Test writes output in Phys path
//File.WriteAllBytes(#"OutPDFa.pdf", Convertstream.ToArray());
byte[] filledPDfa = Convertstream.ToArray();
return filledPDfa;
}
}
// End Convert and Attached
}
i tried get origin properties with these code :
static Dictionary<string, string> GetPdfProperties(byte[] originfile)
{
Dictionary<string, string> propertyInfo = null;
using (PdfReader reader = new PdfReader(originfile))
{
propertyInfo = reader.Info;
reader.Close();
}
return propertyInfo;
}
And Copy origin properties to PDF-A like this :
static byte[] CopyProps(byte[] fileinput,byte[] fileOrigin,PdfAWriter wr)
{
using (var rd = new PdfReader(fileinput))
{
using (var outp = new MemoryStream())
{
using (var stamper = new PdfAStamper(rd, outp,PdfAConformanceLevel.PDF_A_3U))
{
var info = rd.Info;
Dictionary<string, string> propertyInfo = GetPdfProperties(fileOrigin);
foreach (KeyValuePair<string, string> property in propertyInfo)
{
info[property.Key] = property.Value;
}
stamper.MoreInfo = info;
using (var ms = new MemoryStream())
{
wr.CreateXmpWriter(ms,info); //****error was here
stamper.XmpMetadata = ms.ToArray();
}
}
return outp.ToArray();
}
}
}
but found the error was inaccesable due to its protected level
Should i place the error line to another ?
Or
Have another solution for these problem ?
Please Help :(
i use iTextSharp 5.5.13
Using the sample codes from here I come up with these codes -
var my_html = this.GetmyReportHtml();
var my_css = this.GetmyReportHtmlCss();
Byte[] bytes;
using (var ms = new MemoryStream())
{
using (var doc = new iTextSharp.text.Document(PageSize.LETTER))
{
using (var writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
try
{
using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(my_css)))
{
using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(my_html)))
{
iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss);
}
}
}
catch (Exception ex)
{
}
finally
{
doc.Close();
}
}
}
bytes = ms.ToArray();
}
System.IO.File.WriteAllBytes(#"c:\\temp\test.pdf", bytes);
PDF has been generated. However my_html has 6 pages in my case, only half of the content are converted to pdf.
Anyone knows what happened here? How to know if iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml works properly?
Thanks
Found out the problem. In this line of codes -
using (var doc = new iTextSharp.text.Document(PageSize.LETTER))
PageSize.LETTER can not be passed in.
I'm generating a PDF document based on template. The document has multiple pages. The document can have about 5000 pages. When creating the 500-th page I get an overflow RAM (memory). Any idea?
public static void CreateBankBlank2012Year(string pdfTemplatePath, string directoryOutPdf, string nameOutPdf, AnnualReportsFilterParameters filterParametrs, string serverPath)
{
// Get details salary
IEnumerable<SalayDetailsForPdf> dataSalaryDetails = (IEnumerable<SalayDetailsForPdf>) GetSalaryData(filterParametrs);
String fontPath = Path.Combine(serverPath + "\\Fonts", "STSONG.ttf");
Font font = FontFactory.GetFont(fontPath, BaseFont.IDENTITY_H, 8);
using (Document document = new Document())
{
using (PdfSmartCopy copy = new PdfSmartCopy(
document, new FileStream(directoryOutPdf + nameOutPdf, FileMode.Create))
)
{
document.Open();
foreach (var data in dataSalaryDetails)
{
PdfReader reader = new PdfReader(pdfTemplatePath + #"\EmptyTemplateBankBlank_2012.pdf");
using (var ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(reader, ms))
{
stamper.AcroFields.AddSubstitutionFont(font.BaseFont);
AcroFields form = stamper.AcroFields;
form.SetField("t1_address1", data.Address1);
form.SetField("t1_name", data.NameHieroglyphic);
// Other field ...
stamper.FormFlattening = true;
}
reader = new PdfReader(ms.ToArray());
copy.AddPage(copy.GetImportedPage(reader, 1));
}
}
}
}
}
p.s
I'm trying resolve my problem as follow:
generating empty pages based on template
private static void GeneratePdfFromTemplate(string directoryOutPdf, string nameOutPdf, string pdfTemplatePath, int countPages)
{
using (Document document = new Document())
{
using (PdfSmartCopy copy = new PdfSmartCopy(
document, new FileStream(directoryOutPdf + nameOutPdf, FileMode.Create))
)
{
document.Open();
PdfReader reader = new PdfReader(pdfTemplatePath + #"\EmptyTemplateBankBlank_2012.pdf");
for (int i = 0; i < countPages; i++)
{
copy.AddPage(copy.GetImportedPage(reader, 1));
}
reader.Close();
copy.Close();
}
document.Close();
}
GC.Collect();
}
But after a generating I can't set values to the fields.
I'm found solution for my problem, if anyone else would be interested :
private static void SettingFieltValue(Font font, IEnumerable<SalayDetailsForPdf> dataSalaryDetails, int selectedYear, string directoryOutPdf, string nameOutPdf, string pdfTemplatePath)
{
string pdfTemplate = pdfTemplatePath + #"\EmptyTemplateBankBlank_2012.pdf";
string newFile = directoryOutPdf + nameOutPdf;
var fs = new FileStream(newFile, FileMode.Create);
var conc = new PdfConcatenate(fs, true);
foreach (var data in dataSalaryDetails)
{
var reader = new PdfReader(pdfTemplate);
using (var ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(reader, ms))
{
stamper.AcroFields.AddSubstitutionFont(font.BaseFont);
AcroFields form = stamper.AcroFields;
form.SetField("t1_name", data.NameHieroglyphic);
//Other field
stamper.FormFlattening = true;
stamper.Close();
}
reader = new PdfReader(ms.ToArray());
ms.Close();
}
conc.AddPages(reader);
reader.Close();
}
conc.Close();
}
The code snippet below returns a corrupt PDF document however if I return mergedDocument instead it always returns a valid PDF. mergedDocument is based on a PDF file i created using Word, whereas completed document is entirely programmatically generated. The code "works" in that it throws no exceptions. Why is iTextSharp creating a corrupt PDF?
byte[] completedDocument = null;
using (MemoryStream streamCompleted = new MemoryStream())
{
using (Document document = new Document())
{
PdfCopy copy = new PdfCopy(document, streamCompleted);
document.Open();
copy.Open();
foreach (var item in eventItems)
{
byte[] mergedDocument = null;
PdfReader reader = new PdfReader(pdfTemplates[item.DataTokens[NotifyTokenType.OrganisationID]]);
using (MemoryStream streamTemplate = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(reader, streamTemplate))
{
foreach (var token in item.DataTokens)
{
if (stamper.AcroFields.Fields.Any(fld => fld.Key == token.Key.ToString()))
{
stamper.AcroFields.SetField(token.Key.ToString(), token.Value);
}
}
stamper.FormFlattening = true;
stamper.Writer.CloseStream = false;
}
mergedDocument = new byte[streamTemplate.Length];
streamTemplate.Position = 0;
streamTemplate.Read(mergedDocument, 0, (int)streamTemplate.Length);
}
reader = new PdfReader(mergedDocument);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
document.SetPageSize(PageSize.A4);
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
completedDocument = new byte[streamCompleted.Length];
streamCompleted.Position = 0;
streamCompleted.Read(completedDocument, 0, (int)streamCompleted.Length);
}
}
return completedDocument;
You need to close the document and copy objects to flush the PDF writing buffer. This, however, causes some problems when trying to read the stream into an array. The fix for that is to use the ToArray() method of the MemoryStream which still works on closed streams. The changes I made have comments on them.
byte[] completedDocument = null;
using (MemoryStream streamCompleted = new MemoryStream())
{
using (Document document = new Document())
{
PdfCopy copy = new PdfCopy(document, streamCompleted);
document.Open();
copy.Open();
foreach (var item in eventItems)
{
byte[] mergedDocument = null;
PdfReader reader = new PdfReader(pdfTemplates[item.DataTokens[NotifyTokenType.OrganisationID]]);
using (MemoryStream streamTemplate = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(reader, streamTemplate))
{
foreach (var token in item.DataTokens)
{
if (stamper.AcroFields.Fields.Any(fld => fld.Key == token.Key.ToString()))
{
stamper.AcroFields.SetField(token.Key.ToString(), token.Value);
}
}
stamper.FormFlattening = true;
stamper.Writer.CloseStream = false;
}
//Copy the stream's bytes
mergedDocument = streamTemplate.ToArray();
}
reader = new PdfReader(mergedDocument);
for (int i = 1; i <= reader.NumberOfPages; i++)
{
document.SetPageSize(PageSize.A4);
copy.AddPage(copy.GetImportedPage(reader, i));
}
//Close the document and the copy
document.Close();
copy.Close();
}
//ToArray() can operate on closed streams
completedDocument = streamCompleted.ToArray();
}
}
return completedDocument;
Also make sure your html doesn't contains hr tag while converting html to pdf
hdnEditorText.Value.Replace("\"", "'").Replace("<hr />", "").Replace("<hr/>", "")