Combinez deux (ou plusieurs) PDF

Contexte: Je dois fournir un ensemble de rapports hebdomadaires à mon personnel de vente. Ce paquet contient plusieurs (5-10) rapports de cristal.

Problème: je voudrais autoriser un utilisateur à exécuter tous les rapports et à exécuter un seul rapport. Je pensais pouvoir le faire en créant les rapports et en faisant ensuite:

List reports = new List(); reports.Add(new WeeklyReport1()); reports.Add(new WeeklyReport2()); reports.Add(new WeeklyReport3());  foreach (ReportClass report in reports) { report.ExportToDisk(ExportFormatType.PortableDocFormat, @"c:\reports\" + report.ResourceName + ".pdf"); } 

Cela me fournirait un dossier complet des rapports, mais je voudrais envoyer à tous un fichier PDF avec tous les rapports hebdomadaires. Je dois donc les combiner.

Existe-t-il un moyen facile de le faire sans installer d’autres contrôles tiers? J’ai déjà DevExpress & CrystalReports et je préfère ne pas en append trop.

Serait-il préférable de les combiner dans la boucle foreach ou dans une boucle séparée? (ou une autre manière)

Merci

J’ai dû résoudre un problème similaire et j’ai fini par créer un petit utilitaire pdfmerge qui utilise le projet PDFSharp qui est essentiellement sous licence MIT.

Le code est simple, j’avais besoin d’un utilitaire cmdline, donc j’ai plus de code dédié à l’parsing des arguments que pour la fusion PDF:

 using (PdfDocument one = PdfReader.Open("file1.pdf", PdfDocumentOpenMode.Import)) using (PdfDocument two = PdfReader.Open("file2.pdf", PdfDocumentOpenMode.Import)) using (PdfDocument outPdf = new PdfDocument()) { CopyPages(one, outPdf); CopyPages(two, outPdf); outPdf.Save("file1and2.pdf"); } void CopyPages(PdfDocument from, PdfDocument to) { for (int i = 0; i < from.PageCount; i++) { to.AddPage(from.Pages[i]); } } 

Voici une fonction unique qui fusionnera X quantité de fichiers PDF à l’aide de PDFSharp

 public static void MergePDFs(ssortingng targetPath, params ssortingng[] pdfs) { using(PdfDocument targetDoc = new PdfDocument()){ foreach (ssortingng pdf in pdfs) { using (PdfDocument pdfDoc = PdfReader.Open(pdf, PdfDocumentOpenMode.Import)) { for (int i = 0; i < pdfDoc.PageCount; i++) { targetDoc.AddPage(pdfDoc.Pages[i]); } } } targetDoc.Save(targetPath); } } 

PDFsharp semble permettre de fusionner plusieurs documents PDF en un seul.

Et la même chose est également possible avec ITextSharp .

C’est quelque chose que j’ai compris et que je voulais partager avec vous.

  public static byte[] MergePdf(List pdfs) { List lstDocuments = new List(); foreach (var pdf in pdfs) { lstDocuments.Add(PdfReader.Open(new MemoryStream(pdf), PdfDocumentOpenMode.Import)); } using (PdfSharp.Pdf.PdfDocument outPdf = new PdfSharp.Pdf.PdfDocument()) { for(int i = 1; i<= lstDocuments.Count; i++) { foreach(PdfSharp.Pdf.PdfPage page in lstDocuments[i-1].Pages) { outPdf.AddPage(page); } } MemoryStream stream = new MemoryStream(); outPdf.Save(stream, false); byte[] bytes = stream.ToArray(); return bytes; } } 

Il y a déjà de bonnes réponses, mais je pensais pouvoir mentionner que pdftk pourrait être utile pour cette tâche. Au lieu de produire directement un PDF, vous pouvez produire chaque PDF dont vous avez besoin, puis les combiner en un post-processus avec pdftk. Cela pourrait même être fait à partir de votre programme en utilisant un appel system () ou ShellExecute ().

Voici un lien vers un exemple utilisant PDFSharp et ConcatenateDocuments

Je sais que beaucoup de gens ont recommandé PDF Sharp, mais il ne semble pas que ce projet ait été mis à jour depuis juin 2008. De plus, la source n’est pas disponible.

Personnellement, je joue avec iTextSharp, qui est assez facile à utiliser.

J’ai utilisé iTextsharp avec c # pour combiner des fichiers pdf. C’est le code que j’ai utilisé.

 ssortingng[] lstFiles=new ssortingng[3]; lstFiles[0]=@"C:/pdf/1.pdf"; lstFiles[1]=@"C:/pdf/2.pdf"; lstFiles[2]=@"C:/pdf/3.pdf"; PdfReader reader = null; Document sourceDocument = null; PdfCopy pdfCopyProvider = null; PdfImportedPage importedPage; ssortingng outputPdfPath=@"C:/pdf/new.pdf"; sourceDocument = new Document(); pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPdfPath, System.IO.FileMode.Create)); //Open the output file sourceDocument.Open(); try { //Loop through the files list for (int f = 0; f < lstFiles.Length-1; f++) { int pages =get_pageCcount(lstFiles[f]); reader = new PdfReader(lstFiles[f]); //Add pages of current file for (int i = 1; i <= pages; i++) { importedPage = pdfCopyProvider.GetImportedPage(reader, i); pdfCopyProvider.AddPage(importedPage); } reader.Close(); } //At the end save the output file sourceDocument.Close(); } catch (Exception ex) { throw ex; } private int get_pageCcount(string file) { using (StreamReader sr = new StreamReader(File.OpenRead(file))) { Regex regex = new Regex(@"/Type\s*/Page[^s]"); MatchCollection matches = regex.Matches(sr.ReadToEnd()); return matches.Count; } } 

Combinant deux byte[] utilisant iTextSharp jusqu’à la version 5.x:

 internal static MemoryStream mergePdfs(byte[] pdf1, byte[] pdf2) { MemoryStream outStream = new MemoryStream(); using (Document document = new Document()) using (PdfCopy copy = new PdfCopy(document, outStream)) { document.Open(); copy.AddDocument(new PdfReader(pdf1)); copy.AddDocument(new PdfReader(pdf2)); } return outStream; } 

Au lieu de l’ byte[] , il est possible de passer aussi à Stream .

J’ai combiné les deux ci-dessus, parce que je devais fusionner 3 pdfbytes et retourner un octet

 internal static byte[] mergePdfs(byte[] pdf1, byte[] pdf2,byte[] pdf3) { MemoryStream outStream = new MemoryStream(); using (Document document = new Document()) using (PdfCopy copy = new PdfCopy(document, outStream)) { document.Open(); copy.AddDocument(new PdfReader(pdf1)); copy.AddDocument(new PdfReader(pdf2)); copy.AddDocument(new PdfReader(pdf3)); } return outStream.ToArray(); } 

Voici la solution http://www.wacdesigns.com/2008/10/03/merge-pdf-files-using-c Il utilise la bibliothèque iTextSharp open source gratuite http://sourceforge.net/projects/itextsharp

Je l’ai fait avec PDFBox. Je suppose que cela fonctionne de manière similaire à iTextSharp.

Vous pouvez essayer pdf-shuffler gtk-apps.org

La méthode suivante obtient une List de tableau d’ byte qui est byte tableau d’ byte PDF, puis retourne un tableau d’ byte .

 using ...; using PdfSharp.Pdf; using PdfSharp.Pdf.IO; public static class PdfHelper { public static byte[] PdfConcat(List lstPdfBytes) { byte[] res; using (var outPdf = new PdfDocument()) { foreach (var pdf in lstPdfBytes) { using (var pdfStream = new MemoryStream(pdf)) using (var pdfDoc = PdfReader.Open(pdfStream, PdfDocumentOpenMode.Import)) for (var i = 0; i < pdfDoc.PageCount; i++) outPdf.AddPage(pdfDoc.Pages[i]); } using (var memoryStreamOut = new MemoryStream()) { outPdf.Save(memoryStreamOut, false); res = Stream2Bytes(memoryStreamOut); } } return res; } public static void DownloadAsPdfFile(string fileName, byte[] content) { var ms = new MemoryStream(content); HttpContext.Current.Response.Clear(); HttpContext.Current.Response.ContentType = "application/pdf"; HttpContext.Current.Response.AddHeader("content-disposition", $"attachment;filename={fileName}.pdf"); HttpContext.Current.Response.Buffer = true; ms.WriteTo(HttpContext.Current.Response.OutputStream); HttpContext.Current.Response.End(); } private static byte[] Stream2Bytes(Stream input) { var buffer = new byte[input.Length]; using (var ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) ms.Write(buffer, 0, read); return ms.ToArray(); } } } 

Le résultat de la méthode PdfHelper.PdfConcat est donc transmis à la méthode PdfHelper.DownloadAsPdfFile .

PS: Un package NuGet nommé [PdfSharp][1] doit être installé. Donc, dans le type de fenêtre Package Manage Console :

Paquet d’installation PdfSharp

Voici un exemple d’utilisation de iTextSharp

 public static void MergePdf(Stream outputPdfStream, IEnumerable pdfFilePaths) { using (var document = new Document()) using (var pdfCopy = new PdfCopy(document, outputPdfStream)) { pdfCopy.CloseStream = false; try { document.Open(); foreach (var pdfFilePath in pdfFilePaths) { using (var pdfReader = new PdfReader(pdfFilePath)) { pdfCopy.AddDocument(pdfReader); pdfReader.Close(); } } } finally { document?.Close(); } } } 

Le constructeur PdfReader a de nombreuses surcharges. Il est possible de remplacer le type de paramètre IEnumerable par IEnumerable et cela devrait également fonctionner. Notez que la méthode ne ferme pas le OutputStream, il délègue cette tâche au créateur du stream.

La méthode suivante fusionne deux fichiers PDF (f1 et f2) en utilisant iTextSharp. Le second pdf est ajouté après un index spécifique de f1.

  ssortingng f1 = "D:\\a.pdf"; ssortingng f2 = "D:\\Iso.pdf"; ssortingng outfile = "D:\\c.pdf"; appendPagesFromPdf(f1, f2, outfile, 3); public static void appendPagesFromPdf(Ssortingng f1,ssortingng f2, Ssortingng destinationFile, int startingindex) { PdfReader p1 = new PdfReader(f1); PdfReader p2 = new PdfReader(f2); int l1 = p1.NumberOfPages, l2 = p2.NumberOfPages; //Create our destination file using (FileStream fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.None)) { Document doc = new Document(); PdfWriter w = PdfWriter.GetInstance(doc, fs); doc.Open(); for (int page = 1; page <= startingindex; page++) { doc.NewPage(); w.DirectContent.AddTemplate(w.GetImportedPage(p1, page), 0, 0); //Used to pull individual pages from our source }// copied pages from first pdf till startingIndex for (int i = 1; i <= l2;i++) { doc.NewPage(); w.DirectContent.AddTemplate(w.GetImportedPage(p2, i), 0, 0); }// merges second pdf after startingIndex for (int i = startingindex+1; i <= l1;i++) { doc.NewPage(); w.DirectContent.AddTemplate(w.GetImportedPage(p1, i), 0, 0); }// continuing from where we left in pdf1 doc.Close(); p1.Close(); p2.Close(); } }