Merging Memory Streams to create a http PDF response in c# - c#

I am trying to merge 2 crystal reports into single pdf file and I'm using Itextsharp v5.1.1. But it says the document cannot be opened. It might be corrupted. There are no build errors. but the pdf is malformed and cant be opened. Here is the order I chose to accomplish this.
Export the Crystal report to MemoryStream1 in pdf format
Export the second report into MemoryStream2.
Merge the Memory Streams
Send the Streams to Http Output Response as PDF.
Here is the Code for each step in the order.
/// Get the Dataset from Stored Procedure for the CSSource Report
dsCS = CSData.GetUSSourceXML(ds_input);
/// Create the Report of type CSsource
rptCS = ReportFactory.GetReport(typeof(CSsource));
rptCS .SetDataSource(dsCS);
/// Set the Parameters to the CS report
rptCS .ParameterFields["Parameterid"].CurrentValues.Clear();
rptCS .SetParameterValue("Parameterid", PID);
//// Serialize the Object as PDF
msCS=(MemoryStream)rptCS .ExportToStream(ExportFormatType.PortableDocFormat);
For Step 2
/// Get the Dataset from Stored Procedure for the Aden Report
dsAd = CSData.GetAdden(ds_input);
/// Create the Report of type Aden
rptAd = ReportFactory.GetReport(typeof(Aden));
rptAd.SetDataSource(dsAd );
/// Set the Parameters to the Aden report
rptAd.ParameterFields["Parameterid"].CurrentValues.Clear();
rptAd.SetParameterValue("Parameterid", PID);
//// Serialize the Object as PDF
msAD = (MemoryStream)rptAd.ExportToStream(ExportFormatType.PortableDocFormat);
For Step 3
System.Collections.Generic.List<byte[]> sourceFiles = new List<byte[]>();
sourceFiles.Add(msCS.ToArray());
sourceFiles.Add(msAD.ToArray());
PdfMerger mpdfs = new PdfMerger();
/// ms is the Memory stream to which both the streams are added
ms=mpdfs.MergeFiles(sourceFiles);
MergeFiles method is as follows
public MemoryStream MergeFiles(Generic.List<byte[]> sourceFiles)
{
Document document = new Document();
MemoryStream output = new MemoryStream();
try
{
// Initialize pdf writer
PdfWriter writer = PdfWriter.GetInstance(document, output);
//writer.PageEvent = new PdfPageEvents();
// Open document to write
document.Open();
PdfContentByte content = writer.DirectContent;
// Iterate through all pdf documents
for (int fileCounter = 0; fileCounter < sourceFiles.Count;
fileCounter++)
{
// Create pdf reader
PdfReader reader = new PdfReader(sourceFiles[fileCounter]);
int numberOfPages = reader.NumberOfPages;
// Iterate through all pages
for (int currentPageIndex = 1; currentPageIndex <=
numberOfPages; currentPageIndex++)
{
// Determine page size for the current page
document.SetPageSize(
reader.GetPageSizeWithRotation(currentPageIndex));
// Create page
document.NewPage();
PdfImportedPage importedPage =
writer.GetImportedPage(reader, currentPageIndex);
// Determine page orientation
int pageOrientation =
reader.GetPageRotation(currentPageIndex);
if ((pageOrientation == 90) || (pageOrientation == 270))
{
content.AddTemplate(importedPage, 0, -1f, 1f, 0, 0,
reader.GetPageSizeWithRotation(currentPageIndex).Height);
}
else
{
content.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
}
}
}
}
catch (Exception exception)
{
throw new Exception("There has an unexpected exception" +
" occured during the pdf merging process.", exception);
}
finally
{
// document.Close();
}
return output;
}
Step 4 to Serialize the Memory stream as PDF
// ms is the memory stream which is to be converted to PDF
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.Charset = string.Empty;
Response.AddHeader("Content-Disposition",
"attachment; filename=" +
"Application of " + FullName.Trim() + ".pdf");
//Write the file directly to the HTTP content output stream.
Response.OutputStream.Write(ms.ToArray(), 0,
Convert.ToInt32(ms.Length));
Response.OutputStream.Flush();
Response.OutputStream.Close();
rptCS.Close();
rptCS.Dispose();
rptAd.Close();
rptAd.Dispose();
Thanks for all those Developers helping me with this.
This is Urgent because it has to go production in a day or 2.
Please respond.
Chandanan.

Here's a simple merge method that copies PDF files into one PDF. I use this method quite often when merging pdfs. Hope it helps.
public MemoryStream MergePdfForms(List<byte[]> files)
{
if (files.Count > 1)
{
PdfReader pdfFile;
Document doc;
PdfWriter pCopy;
MemoryStream msOutput = new MemoryStream();
pdfFile = new PdfReader(files[0]);
doc = new Document();
pCopy = new PdfSmartCopy(doc, msOutput);
doc.Open();
for (int k = 0; k < files.Count; k++)
{
pdfFile = new PdfReader(files[k]);
for (int i = 1; i < pdfFile.NumberOfPages + 1; i++)
{
((PdfSmartCopy)pCopy).AddPage(pCopy.GetImportedPage(pdfFile, i));
}
pCopy.FreeReader(pdfFile);
}
pdfFile.Close();
pCopy.Close();
doc.Close();
return msOutput;
}
else if (files.Count == 1)
{
return new MemoryStream(files[0]);
}
return null;
}
Step 4 try:
rptCS.Close();
rptCS.Dispose();
rptAd.Close();
rptAd.Dispose();
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition",
"attachment; filename=" +
"Application of " + FullName.Trim() + ".pdf");
Response.BinaryWrite(ms.ToArray());
ApplicationInstance.CompleteRequest();

Related

Error when sending to browser generated PDF using iTextSharp "ERROR: Failed to load PDF document."

I have a function in my controller which receives an object and uses the object's data to fill a PDF. I want to send this PDF to the client so he can download it.However When I submit the form and download the generated PDF i get an error saying "ERROR: Failed to load PDF document."
Here is my code so far:
private void crear_pdf_ZURICH(Seguro seguro)
{
var nombre_pdf = seguro.Nombre + ".pdf";
string oldFile = Server.MapPath("pdf") + "\\" + nombre_pdf;
string newFile = Server.MapPath("pdf") + "\\" + "nuevo_" + nombre_pdf;
using (var reader = new PdfReader(oldFile))
{
using (var fileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
//VARIABLES
for (var i = 1; i <= reader.NumberOfPages; i++)
{
document.NewPage();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
var importedPage = writer.GetImportedPage(reader, i);
var contentByte = writer.DirectContent;
contentByte.AddTemplate(importedPage, 0, 0);
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 10);
if (reader.NumberOfPages - (reader.NumberOfPages - i) == 1)
{
//WRITE SOME STUFF
}
else if (reader.NumberOfPages - (reader.NumberOfPages - i) == 2)
{
//WRITE SOME OTHER STUFF
}
contentByte.EndText();
}
document.Close();
writer.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename="+newFile));
}
}
}
And this is my code working properly, it creates the PDF and I can open it without any problem, however I'm saving it on the server which can cause problems if multiple users are trying to create and download the generated PDF directly from the server.
Here is my code:
private void crear_pdf_ZURICH(Seguro seguro)
{
var nombre_pdf = seguro.Nombre + ".pdf";
string oldFile = Server.MapPath("pdf") + "\\" + nombre_pdf;
string newFile = Server.MapPath("pdf") + "\\" + "nuevo_" + nombre_pdf;
using (var reader = new PdfReader(oldFile))
{
using (var fileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
//VARIABLES
for (var i = 1; i <= reader.NumberOfPages; i++)
{
document.NewPage();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
var importedPage = writer.GetImportedPage(reader, i);
var contentByte = writer.DirectContent;
contentByte.AddTemplate(importedPage, 0, 0);
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 10);
if (reader.NumberOfPages - (reader.NumberOfPages - i) == 1)
{
//WRITE SOME STUFF
}
else if (reader.NumberOfPages - (reader.NumberOfPages - i) == 2)
{
//WRITE SOME STUFF
}
contentByte.EndText();
}
document.Close();
writer.Close();
}
}
}
Thanks in advance if someone can help/explain me how to solve this issue.

Annotations not copying when combining 2 Pdfs [duplicate]

I have the following problem when printing the pdf file after merge, the pdf documents get cut off.
Sometimes this happens because the documents aren't 8.5 x 11
they might be like 11 x 17.
Can we make it detect the page size and then use that same page size for those documents?
Or, if not, is it possible to have it fit to page?
Following is the code:
package com.sumit.program;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
public class MergePdf {
public static void main(String[] args) {
try {
List<InputStream> pdfs = new ArrayList<InputStream>();
pdfs.add(new FileInputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\Document1.pdf"));
pdfs.add(new FileInputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\Landscape.pdf"));
OutputStream output = new FileOutputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\merge1.pdf");
MergePdf.concatPDFs(pdfs, output, true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void concatPDFs(List<InputStream> streamOfPDFFiles,
OutputStream outputStream, boolean paginate) {
Document document = new Document();
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
int i=1;
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
System.out.println("Page size is "+pdfReader.getPageSize(1));
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
i++;
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
writer.setCompressionLevel(9);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
System.out.println("No. of pages "+pdfReader.getNumberOfPages());
i=0;
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
Rectangle r=pdfReader.getPageSize(pdfReader.getPageN(pageOfCurrentReaderPDF+1));
if(r.getWidth()==792.0 && r.getHeight()==612.0)
document.setPageSize(PageSize.A4.rotate());
else
document.setPageSize(PageSize.A4);
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
i++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
System.out.println("Width is "+page.getWidth());
System.out.println("Height is "+page.getHeight());
cb.newlineText();
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Merging of Pdfs is done.......");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Using the Document and PdfWriter class in combination with the addTemplate() method to merge documents is a bad idea. That's not what the addTemplate() method is meant for. You have explicitly or implicitly defined the page size for the Document you are working with. With the addTemplate() method, you add PdfImportedPage instances, and
when you add a new page with the same page size and rotation, you throw away all interactivity that exists in that page, but otherwise all is well,
when you add a new page with a different page size and rotation, you get the result you describe. Because of the difference in size, the imported page and the new page do not match. Parts get cut off, extra margins appear, rotations are different, etc.
This is all explained in chapter 6 of my book. You should use PdfCopy instead of PdfWriter. See for instance the FillFlattenMerge2 example:
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
PdfReader reader;
String line = br.readLine();
// loop over readers
// add the PDF to PdfCopy
reader = new PdfReader(baos.toByteArray());
copy.addDocument(reader);
reader.close();
// end loop
document.close();
In your case, you also need to add page numbers, you can do this in a second go, as is done in the StampPageXofY example:
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfContentByte pagecontent;
for (int i = 0; i < n; ) {
pagecontent = stamper.getOverContent(++i);
ColumnText.showTextAligned(pagecontent, Element.ALIGN_RIGHT,
new Phrase(String.format("page %s of %s", i, n)), 559, 806, 0);
}
stamper.close();
reader.close();
Or you can add them while merging, as is done in the MergeWithToc example.
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
PageStamp stamp;
document.open();
int n;
int pageNo = 0;
PdfImportedPage page;
Chunk chunk;
for (Map.Entry<String, PdfReader> entry : filesToMerge.entrySet()) {
n = entry.getValue().getNumberOfPages();
for (int i = 0; i < n; ) {
pageNo++;
page = copy.getImportedPage(entry.getValue(), ++i);
stamp = copy.createPageStamp(page);
chunk = new Chunk(String.format("Page %d", pageNo));
if (i == 1)
chunk.setLocalDestination("p" + pageNo);
ColumnText.showTextAligned(stamp.getUnderContent(),
Element.ALIGN_RIGHT, new Phrase(chunk),
559, 810, 0);
stamp.alterContents();
copy.addPage(page);
}
}
document.close();
for (PdfReader r : filesToMerge.values()) {
r.close();
}
reader.close();
I strongly advise against using PdfWriter to merge documents! It's not impossible if you change the page size and the rotation of the page in the Document class, but you're making it harder on yourself. Moreover: using PdfWriter also throws away all interactivity (links, annotations,...) that exists in the pages you're merging. Your customer may experience that as a bug.

iTextSharp System.OutOfMemoryException

I have an issue with trying to create a large PDF file. Basically I have a list of byte arrays, each containing a PDF in a form of a byte array. I wanted to merge the byte arrays into a single PDF. This works great for smaller files (under 2000 pages), but when I tried creating a 12,00 page file it bombed). Originally I was using MemoryStream but after some research, a common solution was to use a FileStream instead. So I tried a file stream approach, however get similar results. The List contains 3,800 records, each containing 4 pages. MemoryStream bombs after around 570. FileStream after about 680 records. The current file size after the code crashed was 60MB. What am I doing wrong? Here is the code I have, and the code crashes on "copy.AddPage(curPg);" directive, inside the "for(" loop.
private byte[] MergePDFs(List<byte[]> PDFs)
{
iTextSharp.text.Document doc = new iTextSharp.text.Document();
byte[] completePDF;
Guid uniqueId = Guid.NewGuid();
string tempFileName = Server.MapPath("~/" + uniqueId.ToString() + ".pdf");
//using (MemoryStream ms = new MemoryStream())
using(FileStream ms = new FileStream(tempFileName, FileMode.Create, FileAccess.Write, FileShare.Read))
{
iTextSharp.text.pdf.PdfCopy copy = new iTextSharp.text.pdf.PdfCopy(doc, ms);
doc.Open();
int i = 0;
foreach (byte[] PDF in PDFs)
{
i++;
// Create a reader
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(PDF);
// Cycle through all the pages
for (int currentPageNumber = 1; currentPageNumber <= reader.NumberOfPages; ++currentPageNumber)
{
// Read a page
iTextSharp.text.pdf.PdfImportedPage curPg = copy.GetImportedPage(reader, currentPageNumber);
// Add the page over to the rest of them
copy.AddPage(curPg);
}
// Close the reader
reader.Close();
}
// Close the document
doc.Close();
// Close the copier
copy.Close();
// Convert the memorystream to a byte array
//completePDF = ms.ToArray();
}
//return completePDF;
return GetPDFsByteArray(tempFileName);
}
A couple of notes:
PdfCopy implements iDisposable, so you should try and see if a using helps.
PdfCopy.FreeReader() will help.
Anyway, not sure if you're using MVC or WebForms, but here's a simple working HTTP handler tested with a 15 page 125KB test file that runs on my workstation:
<%# WebHandler Language="C#" Class="MergeFiles" %>
using System;
using System.Collections.Generic;
using System.Web;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
public class MergeFiles : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
List<byte[]> pdfs = new List<byte[]>();
var pdf = File.ReadAllBytes(context.Server.MapPath("~/app_data/test.pdf"));
for (int i = 0; i < 4000; ++i) pdfs.Add(pdf);
var Response = context.Response;
Response.ContentType = "application/pdf";
Response.AddHeader(
"content-disposition",
"attachment; filename=MergeLotsOfPdfs.pdf"
);
Response.BinaryWrite(MergeLotsOfPdfs(pdfs));
}
byte[] MergeLotsOfPdfs(List<byte[]> pdfs)
{
using (var ms = new MemoryStream())
{
using (Document document = new Document())
{
using (PdfCopy copy = new PdfCopy(document, ms))
{
document.Open();
for (int i = 0; i < pdfs.Count; ++i)
{
using (PdfReader reader = new PdfReader(
new RandomAccessFileOrArray(pdfs[i]), null))
{
copy.AddDocument(reader);
copy.FreeReader(reader);
}
}
}
}
return ms.ToArray();
}
}
public bool IsReusable { get { return false; } }
}
Tried to make the output file similar to what you described in the question, but YMMV, depending on how large the individual PDFs you're dealing with are in size. Here's the test output from my run:
So after a lot of messing around, I realized that there just was no way around it. However, I did manage to find a work-around. Instead of returning byte array, I return a temp file path, which I then transmit and delete there after.
private string MergeLotsOfPDFs(List<byte[]> PDFs)
{
Document doc = new Document();
Guid uniqueId = Guid.NewGuid();
string tempFileName = Server.MapPath("~/__" + uniqueId.ToString() + ".pdf");
using (FileStream ms = new FileStream(tempFileName, FileMode.Create, FileAccess.Write, FileShare.Read))
{
PdfCopy copy = new PdfCopy(doc, ms);
doc.Open();
int i = 0;
foreach (byte[] PDF in PDFs)
{
i++;
// Create a reader
PdfReader reader = new PdfReader(new RandomAccessFileOrArray(PDF), null);
// Cycle through all the pages
for (int currentPageNumber = 1; currentPageNumber <= reader.NumberOfPages; ++currentPageNumber)
{
// Read a page
PdfImportedPage curPg = copy.GetImportedPage(reader, currentPageNumber);
// Add the page over to the rest of them
copy.AddPage(curPg);
// This is a lie, it still costs money, hue hue hue :)~
copy.FreeReader(reader);
}
reader.Close();
}
// Close the document
doc.Close();
// Close the document
copy.Close();
}
// Return temp file path
return tempFileName;
}
And here is how I send that data to the client.
// Send the merged PDF file to the user.
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
Response.ClearHeaders();
response.ContentType = "application/pdf";
response.AddHeader("Content-Disposition", "attachment; filename=1094C.pdf;");
response.WriteFile(tempFileName);
HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client.
DeleteFile(tempFileName); // Call right after flush but before close
HttpContext.Current.Response.SuppressContent = true; // Gets or sets a value indicating whether to send HTTP content to the client.
HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.
Lastly, here is a fancy DeleteFile method
private void DeleteFile(string fileName)
{
if (File.Exists(fileName))
{
try
{
File.Delete(fileName);
}
catch (Exception ex)
{
//Could not delete the file, wait and try again
try
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
File.Delete(fileName);
}
catch
{
//Could not delete the file still
}
}
}
}

Unable to access a file created in a web application

This is my code which is used in a wcf service. It successfully generates the PDF, but after generating the document, the folder in which the PDF is generated gives the error: "access is denied"
The PDF is closed for the website, but for the continuous web service it is not closed.
string r = builder.ToString();
string pdfname = Fuhre + "_" + ProtokolType + "_" + GeraeteNr + "_" + r;
PdfWriter.GetInstance(document, new FileStream(#"C:\inetpub\wwwroot\protokoll_pdfs\"+pdfname+".pdf",FileMode.Create));
document.Open();
WebClient wc = new WebClient();
string htmlText = html;
//Response.Write(htmlText);
List<IElement> htmlarraylist = HTMLWorker.ParseToList(new StringReader(htmlText), null);
for (int k = 0; k < htmlarraylist.Count; k++)
{
document.Add((IElement)htmlarraylist[k]);
}
pdflink1 = pdfname + ".pdf";
htmlpdflink =""+pdflink1;
document.Close();
You need to be careful to dispose of everything.
using(var filesStream = new FileStream())
{
using(PdfWriter wri = PdfWriter.GetInstance(doc, fileStream))
{
...
}
}
There are a few other objects (Stream, Document) you may want to close. A sample of how to perform the operation is shown below.
FileStream stream = new FileStream(filePath, FileMode.CreateNew);
Document doc = new Document(PageSize.A4, 24, 24, 24, 24);
PdfWriter writer = PdfWriter.GetInstance(doc, stream);
doc.Open();
//PDF writing operations here
writer.Flush();
doc.Close();
writer.Close();
stream.Close();
You want to serve a file to a browser and/or you want to save the file on disk.
In that case, you would benefit from creating the file in memory and then send the bytes to the browser as well as to a file on disk. This is explained in the answer to the following question: Pdf file not loading properly created by the servlet
The answer mentioned above is written in Java, so you'll have to adapt it.
You can do so by looking at other examples. For instance: Create PDF in memory instead of physical file
byte[] pdfBytes;
using(var mem = new MemoryStream())
{
using(PdfWriter wri = PdfWriter.GetInstance(doc, mem))
{
doc.Open();//Open Document to write
Paragraph paragraph = new Paragraph("This is my first line using Paragraph.");
Phrase pharse = new Phrase("This is my second line using Pharse.");
Chunk chunk = new Chunk(" This is my third line using Chunk.");
doc.Add(paragraph);
doc.Add(pharse);
doc.Add(chunk);
}
pdfBytes = mem.ToArray();
}
Now you can write the pdfBytes to the Response object in your web application:
private void ShowPdf(byte[] strS)
{
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=" + DateTime.Now);
Response.BinaryWrite(strS);
Response.End();
Response.Flush();
Response.Clear();
}
And you can reuse the bytes to write them to a File: Can a Byte[] Array be written to a file in C#?
File.WriteAllBytes(string path, byte[] bytes)
If the problem persist, then you know that it isn't caused by iTextSharp, because iTextSharp merely produces the bytes.
In addition to what everyone else said, I strongly recommend you break each process into multiple sections that don't interact and aren't even aware of each other. Then test each section independently as much as possible. For instance:
private void makePDF( filePath )
{
//Create the PDF
}
private void main()
{
//Make the PDF
makePDF( "test.pdf" );
//If this line fails then your makePDF code has an open handle
File.Delete( "test.pdf" );
}
Then continue:
private void makePDF( filePath )
{
//Create the PDF
}
private void emailPDF( filePath )
{
//Email the PDF
}
private void main()
{
//Make the PDF
makePDF( "test.pdf" );
emailPDF( "test.pdf" );
//If this line fails now then your emailPDF code has an open handle
File.Delete( "test.pdf" );
}
The important part if that you don't try 500 things all at once because that leads to "something is locking my file but I don't know what".

download multiple pdf

I am trying to download multiple pdf's as attachments in my asp.net application.I have created some templates and filling values using pdfstamper(itextsharp). I am able to fill the values but not able to download.
private void FillForm(string path, DataTable BridgeValues, DataTable Comments, DataTable Maintenance,string Newfilename)
{
try
{
string pdfTemplate = path;
string newFile = Newfilename;
string Pathser = "";
if (!System.IO.Directory.Exists(Server.MapPath(#"~/PDF/")))
{
System.IO.Directory.CreateDirectory(Server.MapPath(#"~/PDF/"));
}
if (Directory.Exists(Server.MapPath(#"~/PDF/")))
{
Pathser = Server.MapPath(#"~/PDF/" + Newfilename);
}
System.IO.MemoryStream mStream = new System.IO.MemoryStream();
// create a new PDF reader based on the PDF template document
PdfReader pdfReader = new PdfReader(pdfTemplate);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(Pathser, FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
DataColumn dc = null;
for (int i = 0; i < BridgeValues.Columns.Count - 1; i++)
{
dc = BridgeValues.Columns[i];
pdfFormFields.SetField(dc.ColumnName.ToString(), BridgeValues.Rows[0][dc].ToString());
}
pdfStamper.FormFlattening = true;
// close the pdf
pdfStamper.Close();
////Response.ContentType = "application/octet-stream";
Response.ContentType = "application/pdf";
////Response.AddHeader("Content-Disposition", "attachment; filename=Report.pdf");
Response.AddHeader("Content-Disposition", "attachment; filename=" + Newfilename + "");
////Response.BinaryWrite(mStream.ToArray());
Response.TransmitFile(Server.MapPath(("~/PDF/"+ Newfilename)));
Response.Clear();
Response.End();
}
catch (System.Threading.ThreadAbortException lException)
{
// do nothing
}
}
First time I tried to create one pdf ,it worked but later when I tried to download multiple files it gave an execption.
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.
I don't think you can download multiple files by making one request and returning a collection from the action. I would suggest that it you need to allow user to download multiple files you ZIP them and stream the archive down to the browser.
Here is an example of zipping multiple files: http://devpinoy.org/blogs/keithrull/archive/2008/01/25/how-to-create-zip-files-in-c-with-sharpziplib-ziplib.aspx

Categories

Resources