Merging multiple PDFs using iTextSharp in c#.net - c#

Well i'm trying to merge multiple PDFs in to one.
I gives no errors while compiling. I tried to merge the docs first but that went wrong because I'm working with tables.
This is the asp.net code-behind
if (Button.Equals("PreviewWord")) {
String eventTemplate = Server.MapPath("/ERAS/Badges/Template/EventTemp" + EventName + ".doc");
String SinglePreview = Server.MapPath("/ERAS/Badges/Template/PreviewSingle" + EventName + ".doc");
String PDFPreview = Server.MapPath("/ERAS/Badges/Template/PDFPreviewSingle" + EventName + ".pdf");
String previewPDFs = Server.MapPath("/ERAS/Badges/Template/PreviewPDFs" + EventName + ".pdf");
if (System.IO.File.Exists((String)eventTemplate))
{
if (vulGegevensIn == true)
{
//This creates a Worddocument and fills in names etc from database
CreateWordDocument(vulGegevensIn, eventTemplate, SinglePreview, false);
//This saves the SinglePreview.doc as a PDF #param place of PDFPreview
CreatePDF(SinglePreview, PDFPreview);
//Trying to merge
String[] previewsSmall=new String[1];
previewsSmall[0] = PDFPreview;
PDFMergenITextSharp.MergeFiles(previewPDFs, previewsSmall);
}
// merge PDFs here...........................;
//here
//no here//
//...
} }
This is the PDFMergenITextSharpClass
public static class PDFMergenITextSharp
{
public static void MergeFiles(string destinationFile, string[] sourceFiles)
{
try
{
int f = 0;
// we create a reader for a certain document
PdfReader reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
int n = reader.NumberOfPages;
//Console.WriteLine("There are " + n + " pages in the original file.");
// step 1: creation of a document-object
Document document = new Document(reader.GetPageSizeWithRotation(1));
// step 2: we create a writer that listens to the document
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
// step 3: we open the document
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
// step 4: we add content
while (f < sourceFiles.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(reader.GetPageSizeWithRotation(i));
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
//Console.WriteLine("Processed page " + i);
}
f++;
if (f < sourceFiles.Length)
{
reader = new PdfReader(sourceFiles[f]);
// we retrieve the total number of pages
n = reader.NumberOfPages;
//Console.WriteLine("There are " + n + " pages in the original file.");
}
}
// step 5: we close the document
document.Close();
}
catch (Exception e)
{
string strOb = e.Message;
}
}
public static int CountPageNo(string strFileName)
{
// we create a reader for a certain document
PdfReader reader = new PdfReader(strFileName);
// we retrieve the total number of pages
return reader.NumberOfPages;
}
}

I found the answer:
Instead of the 2nd Method, add more files to the first array of input files.
public static void CombineMultiplePDFs(string[] fileNames, string outFile)
{
// step 1: creation of a document-object
Document document = new Document();
//create newFileStream object which will be disposed at the end
using (FileStream newFileStream = new FileStream(outFile, FileMode.Create))
{
// step 2: we create a writer that listens to the document
PdfCopy writer = new PdfCopy(document, newFileStream);
// step 3: we open the document
document.Open();
foreach (string fileName in fileNames)
{
// we create a reader for a certain document
PdfReader reader = new PdfReader(fileName);
reader.ConsolidateNamedDestinations();
// step 4: we add content
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
writer.AddPage(page);
}
PRAcroForm form = reader.AcroForm;
if (form != null)
{
writer.CopyAcroForm(reader);
}
reader.Close();
}
// step 5: we close the document and writer
writer.Close();
document.Close();
}//disposes the newFileStream object
}

I found a very nice solution on this site : http://weblogs.sqlteam.com/mladenp/archive/2014/01/10/simple-merging-of-pdf-documents-with-itextsharp-5-4-5.aspx
I update the method in this mode :
public static bool MergePdfs(IEnumerable<string> fileNames, string targetFileName)
{
bool success = true;
using (FileStream stream = new(targetFileName, FileMode.Create))
{
Document document = new();
PdfCopy pdf = new(document, stream);
PdfReader? reader = null;
try
{
document.Open();
foreach (string file in fileNames)
{
reader = new PdfReader(file);
pdf.AddDocument(reader);
reader.Close();
}
}
catch (Exception)
{
success = false;
reader?.Close();
}
finally
{
document?.Close();
}
}
return success;
}

Code For Merging PDF's in Itextsharp
public static void Merge(List<String> InFiles, String OutFile)
{
using (FileStream stream = new FileStream(OutFile, FileMode.Create))
using (Document doc = new Document())
using (PdfCopy pdf = new PdfCopy(doc, stream))
{
doc.Open();
PdfReader reader = null;
PdfImportedPage page = null;
//fixed typo
InFiles.ForEach(file =>
{
reader = new PdfReader(file);
for (int i = 0; i < reader.NumberOfPages; i++)
{
page = pdf.GetImportedPage(reader, i + 1);
pdf.AddPage(page);
}
pdf.FreeReader(reader);
reader.Close();
File.Delete(file);
});
}
}

Using iTextSharp.dll
protected void Page_Load(object sender, EventArgs e)
{
String[] files = #"C:\ENROLLDOCS\A1.pdf,C:\ENROLLDOCS\A2.pdf".Split(',');
MergeFiles(#"C:\ENROLLDOCS\New1.pdf", files);
}
public void MergeFiles(string destinationFile, string[] sourceFiles)
{
if (System.IO.File.Exists(destinationFile))
System.IO.File.Delete(destinationFile);
string[] sSrcFile;
sSrcFile = new string[2];
string[] arr = new string[2];
for (int i = 0; i <= sourceFiles.Length - 1; i++)
{
if (sourceFiles[i] != null)
{
if (sourceFiles[i].Trim() != "")
arr[i] = sourceFiles[i].ToString();
}
}
if (arr != null)
{
sSrcFile = new string[2];
for (int ic = 0; ic <= arr.Length - 1; ic++)
{
sSrcFile[ic] = arr[ic].ToString();
}
}
try
{
int f = 0;
PdfReader reader = new PdfReader(sSrcFile[f]);
int n = reader.NumberOfPages;
Response.Write("There are " + n + " pages in the original file.");
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
document.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page;
int rotation;
while (f < sSrcFile.Length)
{
int i = 0;
while (i < n)
{
i++;
document.SetPageSize(PageSize.A4);
document.NewPage();
page = writer.GetImportedPage(reader, i);
rotation = reader.GetPageRotation(i);
if (rotation == 90 || rotation == 270)
{
cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else
{
cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
Response.Write("\n Processed page " + i);
}
f++;
if (f < sSrcFile.Length)
{
reader = new PdfReader(sSrcFile[f]);
n = reader.NumberOfPages;
Response.Write("There are " + n + " pages in the original file.");
}
}
Response.Write("Success");
document.Close();
}
catch (Exception e)
{
Response.Write(e.Message);
}
}

Merge byte arrays of multiple PDF files:
public static byte[] MergePDFs(List<byte[]> pdfFiles)
{
if (pdfFiles.Count > 1)
{
PdfReader finalPdf;
Document pdfContainer;
PdfWriter pdfCopy;
MemoryStream msFinalPdf = new MemoryStream();
finalPdf = new PdfReader(pdfFiles[0]);
pdfContainer = new Document();
pdfCopy = new PdfSmartCopy(pdfContainer, msFinalPdf);
pdfContainer.Open();
for (int k = 0; k < pdfFiles.Count; k++)
{
finalPdf = new PdfReader(pdfFiles[k]);
for (int i = 1; i < finalPdf.NumberOfPages + 1; i++)
{
((PdfSmartCopy)pdfCopy).AddPage(pdfCopy.GetImportedPage(finalPdf, i));
}
pdfCopy.FreeReader(finalPdf);
}
finalPdf.Close();
pdfCopy.Close();
pdfContainer.Close();
return msFinalPdf.ToArray();
}
else if (pdfFiles.Count == 1)
{
return pdfFiles[0];
}
return null;
}

I don't see this solution anywhere and supposedly ... according to one person, the proper way to do it is with copyPagesTo(). This does work I tested it. Your mileage may vary between city and open road driving. Goo luck.
public static bool MergePDFs(List<string> lststrInputFiles, string OutputFile, out int iPageCount, out string strError)
{
strError = string.Empty;
PdfWriter pdfWriter = new PdfWriter(OutputFile);
PdfDocument pdfDocumentOut = new PdfDocument(pdfWriter);
PdfReader pdfReader0 = new PdfReader(lststrInputFiles[0]);
PdfDocument pdfDocument0 = new PdfDocument(pdfReader0);
int iFirstPdfPageCount0 = pdfDocument0.GetNumberOfPages();
pdfDocument0.CopyPagesTo(1, iFirstPdfPageCount0, pdfDocumentOut);
iPageCount = pdfDocumentOut.GetNumberOfPages();
for (int ii = 1; ii < lststrInputFiles.Count; ii++)
{
PdfReader pdfReader1 = new PdfReader(lststrInputFiles[ii]);
PdfDocument pdfDocument1 = new PdfDocument(pdfReader1);
int iFirstPdfPageCount1 = pdfDocument1.GetNumberOfPages();
iPageCount += iFirstPdfPageCount1;
pdfDocument1.CopyPagesTo(1, iFirstPdfPageCount1, pdfDocumentOut);
int iFirstPdfPageCount00 = pdfDocumentOut.GetNumberOfPages();
}
pdfDocumentOut.Close();
return true;
}

Please also visit and read this article where I explained everything in detail about How to Merge Multiple PDF Files Into Single PDF Using Itextsharp in C#
Implementation:
try
{
string FPath = "";
// Create For loop for get/create muliple report on single click based on row of gridview control
for (int j = 0; j < Gridview1.Rows.Count; j++)
{
// Return datatable for data
DataTable dtDetail = new My_GlobalClass().GetDataTable(Convert.ToInt32(Gridview1.Rows[0]["JobId"]));
int i = Convert.ToInt32(Gridview1.Rows[0]["JobId"]);
if (dtDetail.Rows.Count > 0)
{
// Create Object of ReportDocument
ReportDocument cryRpt = new ReportDocument();
//Store path of .rpt file
string StrPath = Application.StartupPath + "\\RPT";
StrPath = StrPath + "\\";
StrPath = StrPath + "rptCodingvila_Articles_Report.rpt";
cryRpt.Load(StrPath);
// Assign Report Datasource
cryRpt.SetDataSource(dtDetail);
// Assign Reportsource to Report viewer
CryViewer.ReportSource = cryRpt;
CryViewer.Refresh();
// Store path/name of pdf file one by one
string StrPathN = Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report" + i.ToString() + ".Pdf";
FPath = FPath == "" ? StrPathN : FPath + "," + StrPathN;
// Export Report in PDF
cryRpt.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, StrPathN);
}
}
if (FPath != "")
{
// Check for File Existing or Not
if (System.IO.File.Exists(Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf"))
System.IO.File.Delete(Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf");
// Split and store pdf input file
string[] files = FPath.Split(',');
// Marge Multiple PDF File
MargeMultiplePDF(files, Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf");
// Open Created/Marged PDF Output File
Process.Start(Application.StartupPath + "\\Temp" + "\\Codingvila_Articles_Report.pdf");
// Check and Delete Input file
foreach (string item in files)
{
if (System.IO.File.Exists(item.ToString()))
System.IO.File.Delete(item.ToString());
}
}
}
catch (Exception ex)
{
XtraMessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
Create Function for Marge PDF
public static void MargeMultiplePDF(string[] PDFfileNames, string OutputFile)
{
iTextSharp.text.Document PDFdoc = new iTextSharp.text.Document();
using (System.IO.FileStream MyFileStream = new System.IO.FileStream(OutputFile, System.IO.FileMode.Create))
{
iTextSharp.text.pdf.PdfCopy PDFwriter = new iTextSharp.text.pdf.PdfCopy(PDFdoc, MyFileStream);
if (PDFwriter == null)
{
return;
}
PDFdoc.Open();
foreach (string fileName in PDFfileNames)
{
iTextSharp.text.pdf.PdfReader PDFreader = new iTextSharp.text.pdf.PdfReader(fileName);
PDFreader.ConsolidateNamedDestinations();
for (int i = 1; i <= PDFreader.NumberOfPages; i++)
{
iTextSharp.text.pdf.PdfImportedPage page = PDFwriter.GetImportedPage(PDFreader, i);
PDFwriter.AddPage(page);
}
iTextSharp.text.pdf.PRAcroForm form = PDFreader.AcroForm;
if (form != null)
{
PDFwriter.CopyAcroForm(PDFreader);
}
PDFreader.Close();
}
PDFwriter.Close();
PDFdoc.Close();
}
}

Related

iTextSharp edit PDF's based on SQL Query

I need to edit merging PDF's to have a colored bar on each PDF page based on a value in an SQL database where the PDF filename is also stored. I am not great with C# lists but thought perhaps I could build a supplemental list to the iTextSharp "PDFReader" list then when iterating through the PDFReader list write a conditional statement that says "if list 2 value = "Utilities" then create green square" during the PDF merge process.
protected void Page_Load(object sender, EventArgs e)
{
try
{
if ((Session["AccessLevel"].ToString() == "admin") || (Session["AccessLevel"].ToString() == "worker") || (Session["AccessLevel"].ToString() == "client"))
{
if (Request.QueryString["type"] == "QC")
{
//SqlDataSource2.Update();
}
else
{
}
string checkID = Request.QueryString["id"];
SqlDataReader rdr = null;
SqlConnection con2 = new SqlConnection(sqlConnection);
con2.Open();
//string sqlRowCount = "SELECT COUNT(*) FROM [Attachment] WHERE RequestId = '" + checkID + "' AND AttachType != 'Invoice' AND AttachType != 'Cover Sheet' ORDER BY AttachOrder ASC";
sqlUserName2 = "SELECT AttachmentName,AttachType FROM [Attachment] WHERE RequestId = '" + checkID + "' AND AttachType != 'Invoice' AND AttachType != 'Cover Sheet' ORDER BY AttachOrder ASC";
//SqlCommand cmd = new SqlCommand(sqlRowCount, con2);
//string count = cmd.ExecuteScalar().ToString();
SqlCommand cmd2 = new SqlCommand(sqlUserName2, con2);
rdr = cmd2.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(rdr);
List<PdfReader> readerList = new List<PdfReader>();
List<string> pdfName = new List<string>();
foreach (DataRow row in dt.Rows)
{
PdfReader pdfReader = new PdfReader(Server.MapPath(HttpContext.Current.Request.ApplicationPath + "/uploads/reports/" +
Convert.ToString(row[0])));
readerList.Add(pdfReader);
pdfName.Add(Convert.ToString(row[1]));
//pdfName.Add(rdr["AttachType"].ToString());
}
System.Net.Mime.ContentType contentType = new System.Net.Mime.ContentType();
contentType.MediaType = System.Net.Mime.MediaTypeNames.Application.Pdf;
Document document = new Document(PageSize.A4, 0, 0, 40, 0);
//Get instance response output stream to write output file.
PdfWriter writer = PdfWriter.GetInstance(document, Response.OutputStream);
// document.Header = new HeaderFooter(new Phrase("Header Text"), false);
// Parameters passed on to the function that creates the PDF
String headerText = "";
String footerText = "PAGE";
// Define a font and font-size in points (plus f for float) and pick a color
// This one is for both header and footer but you can also create seperate ones
Font fontHeaderFooter = FontFactory.GetFont("arial", 12f);
fontHeaderFooter.Color = Color.BLACK;
// Apply the font to the headerText and create a Phrase with the result
Chunk chkHeader = new Chunk(headerText, fontHeaderFooter);
Phrase p1 = new Phrase(chkHeader);
// create a HeaderFooter element for the header using the Phrase
// The boolean turns numbering on or off
HeaderFooter header = new HeaderFooter(p1, false);
// Remove the border that is set by default
header.Border = Rectangle.NO_BORDER;
// Align the text: 0 is left, 1 center and 2 right.
header.Alignment = 1;
// add the header to the document
document.Header = header;
// The footer is created in an similar way
// If you want to use numbering like in this example, add a whitespace to the
// text because by default there's no space in between them
if (footerText.Substring(footerText.Length - 1) != " ") footerText += " ";
//string newFooter = footerText + pageCount;
Chunk chkFooter = new Chunk(footerText, fontHeaderFooter);
Phrase p2 = new Phrase(chkFooter);
// Turn on numbering by setting the boolean to true
HeaderFooter footer = new HeaderFooter(p2, true);
footer.Border = Rectangle.NO_BORDER;
footer.Alignment = 1;
document.Footer = footer;
Response.Write(pdfName);
Response.Write("test");
// Open the Document for writing and continue creating its content
document.Open();
foreach (PdfReader reader in readerList)
{
for (int i = 1; i <= reader.NumberOfPages; i++)
{
PdfImportedPage page = writer.GetImportedPage(reader, i);
if ("if list 2 value = "Utilities" then create green square")
{
PdfContentByte cb = writer.DirectContent;
var rect = new iTextSharp.text.Rectangle(200, 200, 100, 100);
rect.Border = iTextSharp.text.Rectangle.LEFT_BORDER | iTextSharp.text.Rectangle.RIGHT_BORDER;
rect.BorderWidth = 5; rect.BorderColor = new BaseColor(2, 3, 0);
cb.Rectangle(rect);
}
document.Add(iTextSharp.text.Image.GetInstance(page));
}
}
document.Close();
Response.AppendHeader("content-disposition", "inline; filename=" + Request.QueryString["id"] + "-Final");
Response.ContentType = "application/pdf";
con2.Close();
Response.Write(pdfName);
}
}
catch
{
// Response.Redirect("~/PDFProblem.aspx", false);
}
}
This is a bit clunky but it works until I refactor it. I simply iterated the second list (pdfName) within the first iTextSharp one (pdfReader) using an incrementing integer to move the second list forward when the first list did:
foreach (PdfReader reader in readerList)
{
for (int i = 1; i <= reader.NumberOfPages; i++)
{
string totalValue = pdfName[nextOne].ToString();
PdfImportedPage page = writer.GetImportedPage(reader, i);
if (totalValue == "Permit")
{
PdfContentByte cb = writer.DirectContent;
var rect = new iTextSharp.text.Rectangle(200, 200, 100, 100);
rect.Border = iTextSharp.text.Rectangle.LEFT_BORDER | iTextSharp.text.Rectangle.RIGHT_BORDER;
rect.BorderWidth = 5; rect.BorderColor = new BaseColor(2, 3, 0);
cb.Rectangle(rect);
}
if (totalValue == "TaxBill")
{
PdfContentByte cb = writer.DirectContent;
var rect = new iTextSharp.text.Rectangle(200, 200, 100, 100);
rect.Border = iTextSharp.text.Rectangle.LEFT_BORDER | iTextSharp.text.Rectangle.RIGHT_BORDER;
rect.BorderWidth = 15; rect.BorderColor = new BaseColor(3, 2, 0);
cb.Rectangle(rect);
}
nextOne = nextOne + 1;
document.Add(iTextSharp.text.Image.GetInstance(page));
}
}

The process cannot access the file '...' because it is being used by another process

I have a code to delete file in my folder, but in my line code, I want to delete two file together with different folder. But I always get an error "the process cannot access.... another process". May be you can correct my code and give me a solution. Thanks
1) I have a code to generate watermark when save file(.pdf):
public bool InsertWaterMark(string path)
{
bool valid = true;
string FileDestination = AppDomain.CurrentDomain.BaseDirectory + "Content/" + path;
string FileOriginal = AppDomain.CurrentDomain.BaseDirectory + "Content/" + path.Replace("FileTemporary", "FileOriginal");
System.IO.File.Copy(FileDestination, FileOriginal);
string watermarkText = "Controlled Copy";
#region process
PdfReader reader1 = new PdfReader(FileOriginal);//startFile
using (FileStream fs = new FileStream(FileDestination, FileMode.Create, FileAccess.Write, FileShare.None))//watermarkedFile
{
using (PdfStamper stamper = new PdfStamper(reader1, fs))
{
int pageCount1 = reader1.NumberOfPages;
PdfLayer layer = new PdfLayer("WatermarkLayer", stamper.Writer);
for (int i = 1; i <= pageCount1; i++)
{
iTextSharp.text.Rectangle rect = reader1.GetPageSize(i);
PdfContentByte cb = stamper.GetUnderContent(i);
cb.BeginLayer(layer);
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 80);
PdfGState gState = new PdfGState();
gState.FillOpacity = 0.15f;
cb.SetGState(gState);
cb.SetColorFill(BaseColor.GRAY);
cb.BeginText();
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, rect.Width / 2, rect.Height / 2, 45f);
cb.EndText();
PdfContentByte canvas = stamper.GetUnderContent(i);
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA_OBLIQUE, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
canvas.SetColorFill(BaseColor.RED);
PdfGState gStateFooter = new PdfGState();
gStateFooter.FillOpacity = 1f;
canvas.SetGState(gStateFooter);
canvas.BeginText();
canvas.SetFontAndSize(bf, 12);
canvas.ShowTextAligned(PdfContentByte.ALIGN_CENTER, '"' + "When printed, this documents are considered uncontrolled" + '"', 300.7f, 10.7f, 0);
canvas.EndText();
cb.EndLayer();
}
}
}
#endregion
return valid;
}
2) And this code i call when delete detail data from one page together.
public ActionResult Delete(string parm)
{
TableEDIS data = db.TableEDISs.FirstOrDefault(e => e.detail_guid_edis == new Guid(parm));
string fisikFile = data.upload_document;
string fisikFileFormulir = data.upload_document_formulir;
if (!string.IsNullOrEmpty(fisikFile))
{
var relativePath = "~/Content/" + fisikFile;
var absolutePath = HttpContext.Server.MapPath(relativePath);
var absolutePathOriginal = HttpContext.Server.MapPath(relativePath.Replace("Temporary", "Original"));
if (Directory.Exists(Path.GetDirectoryName(absolutePath)))
{
System.IO.File.Delete(absolutePath);
}
if (Directory.Exists(Path.GetDirectoryName(absolutePathOriginal)))
{
System.IO.File.Delete(absolutePathOriginal);
}
}
}
I hope you understand what I mean.
Thanks in advance.
My spidey senses tells me you need to call
reader1.Close();

Why when giving files names numbers to the names using a counter it's giving it strange numbers?

The first saved file name on the hard disk is: 201701311645---0 then 201701311645---1 then 201701311645---20 then 201701311645---21 then 201701311645---40 and 201701311645---41
But i want it to be saved as: 201701311645---0 then 201701311645---1 then 201701311645---2 then 201701311645---3 then 201701311645---4 and 201701311645---5
In the top i added a counter variable
private int countFilesNames = 0;
Then in a dowork event i also reset the counter to 0 once so if i start the backgroundworker over again it will start from 0.
private void bgwDownloader_DoWork(object sender, DoWorkEventArgs e)
{
Int32 fileNr = 0;
countFilesNames = 0;
if (this.SupportsProgress) { calculateFilesSize(); }
if (!Directory.Exists(this.LocalDirectory)) { Directory.CreateDirectory(this.LocalDirectory); }
while (fileNr < this.Files.Count && !bgwDownloader.CancellationPending)
{
m_fileNr = fileNr;
downloadFile(fileNr);
if (bgwDownloader.CancellationPending)
{
fireEventFromBgw(Event.DeletingFilesAfterCancel);
cleanUpFiles(this.DeleteCompletedFilesAfterCancel ? 0 : m_fileNr, this.DeleteCompletedFilesAfterCancel ? m_fileNr + 1 : 1);
}
else
{
fileNr += 1;
}
}
}
Then in the downloadFile method
private void downloadFile(Int32 fileNr)
{
FileStream writer = null;
m_currentFileSize = 0;
fireEventFromBgw(Event.FileDownloadAttempting);
FileInfo file = this.Files[fileNr];
Int64 size = 0;
Byte[] readBytes = new Byte[this.PackageSize];
Int32 currentPackageSize;
System.Diagnostics.Stopwatch speedTimer = new System.Diagnostics.Stopwatch();
Int32 readings = 0;
Exception exc = null;
try
{
writer = new FileStream(this.LocalDirectory + "\\" + file.Name +
"---" + countFilesNames + ".png", System.IO.FileMode.Create);
}
catch(Exception err)
{
string ggg = err.ToString();
}
HttpWebRequest webReq;
HttpWebResponse webResp = null;
try
{
webReq = (HttpWebRequest)System.Net.WebRequest.Create(this.Files[fileNr].Path);
webResp = (HttpWebResponse)webReq.GetResponse();
size = webResp.ContentLength;
}
catch (Exception ex) { exc = ex; }
m_currentFileSize = size;
fireEventFromBgw(Event.FileDownloadStarted);
if (exc != null)
{
bgwDownloader.ReportProgress((Int32)InvokeType.FileDownloadFailedRaiser, exc);
}
else
{
m_currentFileProgress = 0;
while (m_currentFileProgress < size && !bgwDownloader.CancellationPending)
{
while (this.IsPaused) { System.Threading.Thread.Sleep(100); }
speedTimer.Start();
currentPackageSize = webResp.GetResponseStream().Read(readBytes, 0, this.PackageSize);
m_currentFileProgress += currentPackageSize;
m_totalProgress += currentPackageSize;
fireEventFromBgw(Event.ProgressChanged);
writer.Write(readBytes, 0, currentPackageSize);
readings += 1;
if (readings >= this.StopWatchCyclesAmount)
{
m_currentSpeed = (Int32)(this.PackageSize * StopWatchCyclesAmount * 1000 / (speedTimer.ElapsedMilliseconds + 1));
speedTimer.Reset();
readings = 0;
}
}
speedTimer.Stop();
writer.Close();
webResp.Close();
if (!bgwDownloader.CancellationPending) { fireEventFromBgw(Event.FileDownloadSucceeded); }
}
fireEventFromBgw(Event.FileDownloadStopped);
countFilesNames += 1;
}
I build the file name:
writer = new FileStream(this.LocalDirectory + "\\" + file.Name +
"---" + countFilesNames + ".png", System.IO.FileMode.Create);
The move the counter forward by 1:
countFilesNames += 1;
But i'm getting other files names then i wanted.
Maybe there is a better way to give the files names some identity ? The problem is that if i will not give the files names some identity it will overwrite the files all the time. The files names are the same the content is not so i need to give each file another name.
Why don't you just increment the counter only when a file is written (since the variable doesn't look like it is accessed elsewhere) and not below:
writer = new FileStream(this.LocalDirectory + "\\" + file.Name +
"---" + countFilesNames++ + ".png", System.IO.FileMode.Create);
This way the counter won't be incremented on errors.

How to ignore protected pdf's?

I am writing on my pdf-word converter and I just received a really strange exception witch makes no sens to me.
Error:PdfiumViewer.PdfException:{"Unsupported security scheme"}
Its the first time that such a exception appears. but I have to be honest that I never tried to convert more then 3-4 files from pdf to word and right now I am doing more then 100 files.
Here is my code I am sry if its too long but I simply do not know on which line the error occurs
public static void PdfToImage()
{
try
{
Application application = null;
application = new Application();
string path = #"C:\Users\chnikos\Desktop\Test\Batch1\";
foreach (string file in Directory.EnumerateFiles(path, "*.pdf"))
{
var doc = application.Documents.Add();
using (var document = PdfiumViewer.PdfDocument.Load(file))
{
int pagecount = document.PageCount;
for (int index = 0; index < pagecount; index++)
{
var image = document.Render(index, 200, 200, true);
image.Save(#"C:\Users\chnikos\Desktop\Test\Batch1\output" + index.ToString("000") + ".png", ImageFormat.Png);
application.Selection.InlineShapes.AddPicture(#"C:\Users\chnikos\Desktop\Test\Batch1\output" + index.ToString("000") + ".png");
}
string getFileName = file.Substring(file.LastIndexOf("\\"));
string getFileWithoutExtras = Regex.Replace(getFileName, #"\\", "");
string getFileWihtoutExtension = Regex.Replace(getFileWithoutExtras, #".pdf", "");
string fileName = #"C:\Users\chnikos\Desktop\Test\Batch1\" + getFileWihtoutExtension;
doc.PageSetup.PaperSize = WdPaperSize.wdPaperA4;
foreach (Microsoft.Office.Interop.Word.InlineShape inline in doc.InlineShapes)
{
.....
}
doc.PageSetup.TopMargin = 28.29f;
doc.PageSetup.LeftMargin = 28.29f;
doc.PageSetup.RightMargin = 30.29f;
doc.PageSetup.BottomMargin = 28.29f;
application.ActiveDocument.SaveAs(fileName, WdSaveFormat.wdFormatDocument);
doc.Close();
string imagePath = #"C:\Users\chnikos\Desktop\Test\Batch1\";
Array.ForEach(Directory.GetFiles(imagePath, "*.png"), delegate(string deletePath) { File.Delete(deletePath); });
}
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e);
}
}
}
}

Pdf Merge Issue in ItextSharp (After Merging Pdfs don't retain their Values)

We are trying to merge three PDFs using ITextSharp. The problem is after merging we are able to get Data from the first PDF only, while the other two PDFs don't retain their values.
All these PDFs have the same structure (i.e. they use the same templates with different data), so my assumption is they are having same fields (AcroFields) which may be creating this problem while merging.
Here is the merge code :
public void MergeFiles(string destinationFile, string[] sourceFiles)
{
try
{
int f = 0;
string outFile = destinationFile;
Document document = null;
PdfCopy writer = null;
while (f < sourceFiles.Length)
{
// Create a reader for a certain document
PdfReader reader = new PdfReader(sourceFiles[f]);
// Retrieve the total number of pages
int n = reader.NumberOfPages;
//Trace.WriteLine("There are " + n + " pages in " + sourceFiles[f]);
if (f == 0)
{
// Step 1: Creation of a document-object
document = new Document(reader.GetPageSizeWithRotation(1));
// Step 2: Create a writer that listens to the document
writer = new PdfCopy(document, new FileStream(outFile, FileMode.Create));
// Step 3: Open the document
document.Open();
}
// Step 4: Add content
PdfImportedPage page;
for (int i = 0; i < n; )
{
++i;
if (writer != null)
{
page = writer.GetImportedPage(reader, i);
writer.AddPage(page);
}
}
PRAcroForm form = reader.AcroForm;
if (form != null)
{
if (writer != null)
{
writer.CopyAcroForm(reader);
}
}
f++;
}
// Step 5: Close the document
if (document != null)
{
document.Close();
}
}
catch (Exception)
{
//handle exception
}
}
This is called as follows :
string[] sourcenames = { #"D:\1.pdf", #"D:\2.pdf", #"D:\3.pdf" };
string destinationname = #"D:\pdf\mergeall\merge3.pdf";
MergeFiles(destinationname, sourcenames);
I figured it out myself after little searching...Following is the solution...
I have created the function to rename the Fields in the PDF,so that after merging the fields will be renamed.
private static int counter = 0;
private void renameFields(PdfReader pdfReader)
{
try
{
string prepend = String.Format("_{0}", counter++);
foreach (DictionaryEntry de in pdfReader.AcroFields.Fields)
{
pdfReader.AcroFields.RenameField(de.Key.ToString(), prepend + de.Key.ToString());
}
}
catch (Exception ex)
{
throw ex;
}
}
This function is called in "MergeFiles" function as follow...
// Create a reader for a certain document
PdfReader reader = new PdfReader(sourceFiles[f]);
renameFields(reader);
// Retrieve the total number of pages
int n = reader.NumberOfPages;

Categories