ITextSharp Adding Multiple PDFStampers to memoryStream - c#

I have a asp.net application that uses ITextSharp 5.4.5.0 to generate certificates. I have the code that generates one certificate working fine, but when I try to bundle these one page certificates into a single multi-page PDF and output the memorystream to the browser I get an error from Adobe Acrobat.
I have a feeling that I'm not adding eachof my byte arroys correctly, but I'm at a loss.
Here is the calling code:
protected void btnMakeCerts_Click(object sender, EventArgs e)
{
ICAgileEntities icae = new ICAgileEntities();
int classid =int.Parse(Request.QueryString["id"]);
var currentClass = (from c in icae.Classes
where c.id == classid
select c).FirstOrDefault();
Response.Clear();
Response.BufferOutput = true;
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=AllCertificates-" + currentClass.Title + ".pdf");
var pagesAll = new List<byte[]>();
pagesAll = Helper.Certificate.ProcessClassCerts(classid);
MemoryStream ms = new MemoryStream();
PdfConcatenate whole = new PdfConcatenate(ms);
foreach (byte[] pageAll in pagesAll)
{
PdfReader partReader = new PdfReader(pageAll);
whole.AddPages(partReader);
partReader.Close();
}
Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
Response.Flush();
Response.End();
}
And this creates the individual pages and returns a byte array:
public static List<byte[]> ProcessClassCerts(int classId)
{
var icae = new ICAgileEntities();
string filename = DateTime.Now.ToString().Replace(#"/", "").Replace(":", "").Replace(" ", "") + ".pdf";
string sFileDir = ConfigurationManager.AppSettings["ServerPath"] + (#"\images\sigs\");
var currentClass = (from c in icae.Classes
where c.id == classId
select c).FirstOrDefault();
//make the Instructor Names
String instName = "test";
var students = (from up in icae.UserProfiles
from cl in up.UserProfile_Class_Details
where cl.ClassId == classId && cl.IsCertPaid == true && cl.IsClassPaid == true
select up);
var currentCourse = (from s in icae.Courses
where s.id == currentClass.CourseID
select s).FirstOrDefault();
var pageBytes = (byte[])null;
var pagesAll = new List<byte[]>();
try
{
string path = ConfigurationManager.AppSettings["ServerPath"] + #"\PDFs\";
int i = 1;
foreach (var s in students)
{
PdfStamper pst = null;
MemoryStream mstr = null;
using (mstr = new MemoryStream())
{
try
{
PdfReader reader = new PdfReader(path + #"\certFormPDF.pdf"); //new PdfReader(GetTemplateBytes());
pst = new PdfStamper(reader, mstr);
var acroFields = pst.AcroFields;
acroFields.SetField("Awardee Name", s.DisplayName);
pst.FormFlattening = true;
pst.SetFullCompression();
}
finally
{
if (pst != null)
pst.Close();
}
}
pageBytes = mstr.ToArray();
pagesAll.Add(pageBytes);
i++;
}
}
finally
{
}
return pagesAll;
}
Thanks for any help you can provide

Related

Memorystream performance issue with multiple users

I have a section in my application that displays a PDF to a user. I'm using memorystream to get this document. Whenever I have more than a handful of users requests a document at the same time the performance of my application slows down. If i have 30+ users it comes to a crawl. Most of my users say it starts to slow as they reach the document. Here is how I call the document
public FileStreamResult GetDocument(bool useDefault)
{
string contentType = string.Empty;
short verificationType = VerificationType();
MemoryStream ms = DocumentToStream(useDefault, out contentType);
if (contentType == string.Empty) contentType = "application/pdf";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ContentType = contentType;
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline;" + FormFileName());
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
HttpContext.Current.Response.OutputStream.Flush();
HttpContext.Current.Response.OutputStream.Close();
HttpContext.Current.Response.End();
ms.Close();
if (verificationType == OBDocVerification.Presentation) SetVerified(verificationType);
return new FileStreamResult(HttpContext.Current.Response.OutputStream, contentType);
}
To get the actual file it does this
private MemoryStream CreatePdfStream(PdfReader pdfDoc, List<MappedField> pdfFields, bool useVerifyButton, bool isLocked, bool isI9, bool isManualUpdate, string state) // 04/26/2018 DS TFS # 3161
{
using (MemoryStream stream = new MemoryStream())
{
PdfStamper stamper = new PdfStamper(pdfDoc, stream);
if (!isLocked)
{
foreach (MappedField mappedFld in pdfFields)
{
if (!string.IsNullOrEmpty(mappedFld.DB_Table))
{
//string v = PDFformFieldValue(mappedFld, this.docLevel);
string v = PDFformFieldValue(mappedFld, this.docLevel, isI9, state); // 10/04/2017 DS TFS # 2768 (added isI9)
if (!string.IsNullOrEmpty(v))
{
stamper.AcroFields.SetField(mappedFld.FormName, v);
}
else
{
stamper.AcroFields.SetField(mappedFld.FormName, string.Empty);
}
if (useVerifyButton)
{
if (!IsPDFformFieldEditable(mappedFld) || !GlobalVariables.IsIE) stamper.AcroFields.SetFieldProperty(mappedFld.FormName, "setfflags", PdfFormField.FF_READ_ONLY, null);
}
}
}
if (isI9) ValidateI9NAFields(ref stamper, pdfFields);
if (!isManualUpdate && GlobalVariables.IsIE) stamper.FormFlattening = true; // 04/26/2018 DS TFS # 3161
}
//else
// stamper.FormFlattening = true;
if (useVerifyButton && GlobalVariables.IsIE)
{
// Add "Verify" button
string alignmentType;
int numberOfPages = pdfDoc.NumberOfPages;
int stampPage = GetVerifyButtonLocation(out alignmentType);
if (stampPage <= 1) stampPage = numberOfPages;
if (stampPage > numberOfPages) stampPage = numberOfPages;
if (alignmentType == string.Empty) alignmentType = "bottom_right";
Rectangle thePage = pdfDoc.GetCropBox(stampPage);
float buttonWidth = 100;
float buttonHeight = 40;
Rectangle ButtonRect = CreateVerifyButtonLocation(thePage, alignmentType, buttonWidth, buttonHeight);
PushbuttonField button = new PushbuttonField(stamper.Writer, ButtonRect, "postSubmit");
button.BackgroundColor = ButtonColor();
button.BorderColor = GrayColor.BLACK;
button.BorderWidth = 1f;
button.BorderStyle = PdfBorderDictionary.STYLE_INSET;
button.TextColor = BaseColor.WHITE;
button.FontSize = 12f;
button.Text = VerifyButtonTitle();
button.Visibility = PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT;
button.Rotation = pdfDoc.GetPageRotation(stampPage);
PdfFormField field = button.Field;
//field.Put(PdfName.TU, new PdfString("Save changes and return to the folder."));
field.Action = PdfAction.CreateSubmitForm(this.submitUrl, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_INCLUDE_NO_VALUE_FIELDS);
stamper.AddAnnotation(field, stampPage);
}
//else
// stamper.FormFlattening = true;
stamper.Close();
return stream;
}
}
I feel like I may be doing something inefficient here.
This is not a memory stream problem at all. Consider storing a generated stream and then serve it directly. If you have a large pdf file and several users than
your code will be executed several times with same result.

EPPlus not downloading excel file with templates

When I use Epplus to export the excel it not downloading the excel file here are my code
public ActionResult ExportDataTableToExcel(string searchBox)
{
FileStream fs = null;
var fileName = "xxxReport";
fs = new FileStream(Server.MapPath(#"~/Content/Templates/xxxReport.xlsx"), FileMode.Open, FileAccess.Read);
var result = new List<xxxReport_Result>();
using (var db = new xxxEntities())
{
if (searchBox != "" && searchBox != null)
{
result = db.xxxReport()
.Where(r => r.Match.Contains(searchBox)
|| r.MD.Contains(searchBox)
|| r.SBU.Contains(searchBox)
|| r.Project.Contains(searchBox)).ToList();
}
else
{
result = db.xxxReport().ToList();
}
}
var results = Mapper.Map<List<ReportModel>>(result);
Debug.WriteLine("End : {0}", DateTime.Now.ToString("HH:mm:ss"));
using (var excel = new ExcelPackage(fs))
{
var workSheet = excel.Workbook.Worksheets.FirstOrDefault();
int i = 11;
results.ToList().ForEach(s =>
{
int col = 2;
workSheet.Cells[i, col++].Value = s.NO;
workSheet.Cells[i, col++].Value = s.Match;
workSheet.Cells[i, col++].Value = s.MD;
workSheet.Cells[i, col++].Value = s.SBU;
workSheet.Cells[i, col++].Value = s.Project;
workSheet.Cells[i, col++].Value = s.BlockUnit;
i++;
});
Response.Clear();
string saveAsFileName = string.Format("{0}_{1:d}.xlsx", fileName, DateTime.Now).Replace("/", "-");
Response.AddHeader("content-disposition", string.Format("attachment;filename={0}", saveAsFileName));
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.BinaryWrite(excel.GetAsByteArray());
Response.End();
}
return JavaScript("Export Complete");
}
When I hit export button I get notthig, I try to debug and there are no error in code but when use console.log to check the results I get something I like this in my results.
���ʮ�����O�&�ת�����o����Tҵ��B*��� ]��(S���d�Ŗ��)��Oe���Ť񡘿p>^����4aπT|����4��_�
This is how I call function
function ExportToExcel() {
$.post("#Url.Action("ExportDataTableToExcel", "xxx")",
{
searchBox1: $("#searchBox1").val(),
searchBox2: $("#searchBox2").val(),
searchBox3: $("#searchBox3").val(),
searchBox4: $("#searchBox4").val()
}).done(function (result) {
console.log(result);
});
}
With MVC you should stay away from directly interacting with the Response object unless you absolutely need to. With that in mind, this should work:
public ActionResult ExportDataTableToExcel(string searchBox)
{
var fileName = "xxxReport";
byte[] excelContent;
// *** code that pulls your data ***
// always try to use a 'using' statement when you can for disposable objects
using (var fs = new FileStream(Server.MapPath(#"~/Content/Templates/xxxReport.xlsx"), FileMode.Open, FileAccess.Read))
using (var excel = new ExcelPackage(fs))
{
// *** manipulate your worksheet here ***
excelContent = excel.GetAsByteArray();
}
string saveAsFileName = string.Format("{0}_{1:d}.xlsx", fileName, DateTime.Now).Replace("/", "-");
return File(excelContent, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", saveAsFileName);
}
MVC controller functions return an ActionResult object that many other classes inherit from, including System.Web.Mvc.FileContentResult which is what the File() function returns (this method is built into System.Web.Mvc.Controller)
I fix it by creating another function to download results file by using "GET" method

How to save the image while updating the BARCODE?

When I am saving an image, it is getting saved by the Barcode name.
But If I modify the barcode name, then the image is gone, not saving.
I have noticed while debugging that the if(System.IO.File.Exists(imageFilePath)) is not executing when I am updating the barcode. But at the time of saving a new one, its executing.
How to correct this?
Updating code
public object Update(ItemEntity item)
{
var val = _itemRepository.Save(item);
if (item.ImageFileName != string.Empty || item.ImageOriginalFileName != string.Empty)
{
string result = JsonConvert.SerializeObject(val);
var definition = new { Success = false, EntryMode = string.Empty, BarCode = string.Empty, ItemCode = string.Empty };
var info = JsonConvert.DeserializeAnonymousType(result, definition);
if (info.Success)
{
if (!string.IsNullOrEmpty(item.ImageOriginalFileName))
this.SaveImage(item.ImageFileName, (item.ImageOriginalFileName == "BARCODE" ? info.ItemCode : item.ImageOriginalFileName == "BARCODEYes" ? item.Barcode : item.ImageOriginalFileName));
}
}
if (item.DeleteImageFileName != string.Empty && item.ImageFileName == string.Empty) // Image file removed but no new image file is uploaded[Bug Id :34754 -No image is uploaded, when a user re-uploads an image after deleting a previous one.]
{
this.DeleteImage(item.DeleteImageFileName);
}
return val;
}
Saving Code
public void SaveImage(string fileName, string originalFileName)
{
string tempFileName = fileName;
if (!string.IsNullOrEmpty(tempFileName))
{
// move file from temp location to actual loation
var webAppPath = System.Web.Hosting.HostingEnvironment.MapPath("~");
var splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
var upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
var UIFolder = "WebUI";
splitPath.AddRange(new string[] { UIFolder, "Temp", "ImageUpload", CurrentSession.UserId.Value.ToString(), "ItemImage" });
var webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
var imageFilePath = Path.Combine(webUIPath.EnsureEndsWith('\\'), tempFileName);
if (System.IO.File.Exists(imageFilePath))
{
splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
splitPath.AddRange(new string[] { "Shared", "ItemImage" });
webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
// Check existence of folder, create if not found and Delete-Create if found
if (!Directory.Exists(webUIPath))
{
Logger.Debug("Create directory :" + webUIPath);
Directory.CreateDirectory(webUIPath);
}
originalFileName = originalFileName + ".jpg";
var imagDestPath = Path.Combine(webUIPath.EnsureEndsWith('\\'), originalFileName);
if (File.Exists(imagDestPath))
{
GC.Collect();
GC.WaitForPendingFinalizers();
Logger.Debug("Delete File :" + imagDestPath);
File.Delete(imagDestPath);
}
byte[] bytes = System.IO.File.ReadAllBytes(imageFilePath);
FileStream fs = new FileStream(imagDestPath, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
}
}
}

Error while opening the excel file created by NPOI

I am using NPOI to export the data to excel. I am forcing the file to be downloaded as an attachment for the user. When the user saves the file on the disk and opens the file it works but fails when he tries to select the open option from the download dialog box. Please see the code below. Not sure what is wrong
var xssfworkbook = new XSSFWorkbook();
var sheet1 = xssfworkbook.CreateSheet("Sheet 1");
//make header row
var row1 = sheet1.CreateRow(0);
var cell0 = row1.CreateCell(0);
cell0.SetCellValue("Firm Id");
var cell1 = row1.CreateCell(1);
cell1.SetCellValue("Account Number");
for (int i = 0; i < result.Count; i++)
{
var row = sheet1.CreateRow(i + 1);
if (result[i].FeeAmount != null)
{
var cellFirmID = row.CreateCell(0);
cellFirmID.SetCellValue(result[i].FirmID);
}
if (result[i].AccountNumber != null)
{
var cellAccountNumber = row.CreateCell(1);
cellAccountNumber.SetCellValue(result[i].AccountNumber);
}
}
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", "BESTINVEST_fee_rebate_loader_.xlsx"));
MemoryStream file = WriteToStream(xssfworkbook);
response.Clear();
response.BinaryWrite(file.ToArray());
response.End();
private MemoryStream WriteToStream(XSSFWorkbook xssfworkbook)
{
MemoryStream file = new MemoryStream();
xssfworkbook.Write(file);
return file;
}
This problem is from "culture". before Create excel:
var culture=new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture=culture;
Thread.CurrentThread.CurrentUICulture=culture;
I would recommend you make sure your cells are unlocked.
I use the following without problems:
var workbook = new XSSFWorkbook();
var members = (obj as IEnumerable<MemberListViewModel>).ToDataSourceResult(request).Data;
var sheet = workbook.CreateSheet(TempData["List"].ToString());
var headerRow = sheet.CreateRow(0);
headerRow.CreateCell(0).SetCellValue("Name");
headerRow.CreateCell(1).SetCellValue("Degrees");
headerRow.CreateCell(2).SetCellValue("Rank");
headerRow.CreateCell(3).SetCellValue("Endowed Professorship");
headerRow.CreateCell(4).SetCellValue("Department");
headerRow.CreateCell(5).SetCellValue("Program");
var font = workbook.CreateFont();
font.Boldweight = (short)NPOI.SS.UserModel.FontBoldWeight.Bold;
XSSFCellStyle style = (XSSFCellStyle)workbook.CreateCellStyle();
style.SetFont(font);
style.FillPattern = NPOI.SS.UserModel.FillPattern.SolidForeground;
style.FillForegroundColor = IndexedColors.Grey25Percent.Index;
style.IsLocked = false;
style.WrapText = true;
for (int i = 0; i < 6; i++)
{
var colStyle = sheet.GetColumnStyle(i);
colStyle.WrapText = !colStyle.WrapText;
sheet.SetDefaultColumnStyle(i, colStyle);
var cell = headerRow.Cells[i];
cell.CellStyle = style;
}
headerRow.RowStyle = style;
sheet.SetColumnWidth(0, 30 * 256);
sheet.SetColumnWidth(1, 20 * 256);
sheet.SetColumnWidth(2, 20 * 256);
sheet.SetColumnWidth(3, 50 * 256);
sheet.SetColumnWidth(4, 30 * 256);
sheet.SetColumnWidth(5, 50 * 256);
int rowNumber = 1;
style = (XSSFCellStyle)workbook.CreateCellStyle();
style.IsLocked = false;
style.WrapText = true;
foreach (MemberListViewModel member in members)
{
var row = sheet.CreateRow(rowNumber++);
row.CreateCell(0).SetCellValue(member.FullName);
row.CreateCell(1).SetCellValue(member.degrees);
row.CreateCell(2).SetCellValue(member.rank);
row.CreateCell(3).SetCellValue(member.endowed_professorship);
row.CreateCell(4).SetCellValue(member.department);
row.CreateCell(5).SetCellValue(member.program);
}
//var colStyle = sheet.GetColumnStyle(3);
//colStyle.WrapText = !colStyle.WrapText;
//sheet.SetDefaultColumnStyle(3, colStyle);
workbook.Write(output);
var fileName = String.Format(
"{0} {2} - {1}.xlsx",
DateTime.Now.ToString("yyyyMMdd-HHmmss"),
Utilities.getUsername(Utilities.GetCurrentUser()), TempData["List"]).Replace(":", "");
var file = File(output.ToArray(), Utilities.ExcelFileContentType, fileName);
var context = System.Web.HttpContext.Current;
context.Response.Clear();
context.Response.ClearContent();
context.Response.ClearHeaders();
context.Response.AddHeader("content-disposition", String.Format("inline;filename=\'{0}\'", fileName));
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
context.Response.ContentType = file.ContentType;
context.Response.AddHeader("content-length", file.FileContents.Length.ToString());
context.Response.BinaryWrite(buffer: file.FileContents.ToArray());
context.Response.Flush();
context.Response.End();
output.Dispose();

Multipage PDF does not open on iPad

I am working with a project where I am generating PDF Files from PSR Files. The PDF Files works fine if its a single page but if It has more than two PSR Files and I generate two files it does not open on iPad and works fine on Desktop.
The Third library tool I am using here is 'dbatuotrack' and I am using C#.
Can anyone please guide me how to resolve this problem?
Thanks,
S.
foreach (var pdfform in pdfPagesID)
{
//dbAutoTrack.PDFWriter.Document objDoc = null;
//dbAutoTrack.PDFWriter.Page objPage = null;
objDoc = new dbAutoTrack.PDFWriter.Document();
pdfPagesID.Clear();
pdfPagesID = GetSpecPageID(pdfform);
if (pdfPagesID.Count > 1)
{
foreach (var pdfPage in pdfPagesID)
{
dbAutoTrack.PDFWriter.Page objPage2 = null;
var lastItem = pdfPagesID.Last();
prefixPageID = prefixSpecPageID(pdfPage);
suffixPageIDPSR = prefixPageID + ".psr";
if (File.Exists(PSRPath + suffixPageIDPSR))
{
objDs = new CDatasheet(this.PSRPath + suffixPageIDPSR, false);
objDs.pdfDbHelper = pdfhelper;
//Giving the specformId as SpecFornName
pdfFormName = "Form" + pdfform + ".pdf";
if (!(pdfPage == pdfPagesID.First()))
{
objPage2 = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage2);
}
else
{
objPage = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage);
}
if (objPage != null)
{
if (pdfWithNotePage == true && pdfPage.Equals(lastItem))
{
objNotePage = objDs.GetNotePage();
objDoc.Pages.Add(objPage);
objDoc.Pages.Add(objNotePage);
}
else
{
//objDoc.Pages.Add(objPage);
//objDoc.Pages.Add(objPage2);
}
fsOutput = new FileStream(TemplatePath + pdfFormName, FileMode.Create, FileAccess.Write);
objDoc.Generate(fsOutput);
}
if (fsOutput != null)
{
fsOutput.Close();
fsOutput.Dispose();
fsOutput = null;
}
}
}
objDoc = null;
objPage = null;
}
This how I tweaked the code to make it work. Thanks for the suggestion DJ KRAZE
foreach (var pdfform in pdfPagesID)
{
//dbAutoTrack.PDFWriter.Document objDoc = null;
//dbAutoTrack.PDFWriter.Page objPage = null;
objDoc = new dbAutoTrack.PDFWriter.Document();
pdfPagesID.Clear();
pdfPagesID = GetSpecPageID(pdfform);
if (pdfPagesID.Count > 1)
{
foreach (var pdfPage in pdfPagesID)
{
dbAutoTrack.PDFWriter.Page objPage2 = null;
var lastItem = pdfPagesID.Last();
prefixPageID = prefixSpecPageID(pdfPage);
suffixPageIDPSR = prefixPageID + ".psr";
if (File.Exists(PSRPath + suffixPageIDPSR))
{
objDs = new CDatasheet(this.PSRPath + suffixPageIDPSR, false);
objDs.pdfDbHelper = pdfhelper;
//Giving the specformId as SpecFornName
pdfFormName = "Form" + pdfform + ".pdf";
if (!(pdfPage == pdfPagesID.First()))
{
objPage2 = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage2);
}
else
{
objPage = objDs.Generate_PDFReport();
objDoc.Pages.Add(objPage);
}
if (objPage != null)
{
if (pdfWithNotePage == true && pdfPage.Equals(lastItem))
{
objNotePage = objDs.GetNotePage();
objDoc.Pages.Add(objPage);
objDoc.Pages.Add(objNotePage);
}
else
{
//objDoc.Pages.Add(objPage);
//objDoc.Pages.Add(objPage2);
}
}
}
}
fsOutput = new FileStream(TemplatePath + pdfFormName, FileMode.Create, FileAccess.Write);
objDoc.Generate(fsOutput);
//This region was the problem, disposing the output everytime.
//Needed it to be included after completion of iteration
if (fsOutput != null)
{
fsOutput.Close();
fsOutput.Dispose();
fsOutput = null;
}
}

Categories