如何将 .pdf 和 .jpg 文件合并为一个 pdf
How to merge .pdf and .jpg file in one pdf
磁盘上有两个文件 .jpg 和 .pdf,我需要读取这两个文件并将它们添加到新的 pdf 并发送到浏览器以便可以下载。
新的 pdf 文件仅包含 pdf 内容而不包含 jpeg 文件图像。
memoryStream myMemoryStream = new MemoryStream();
//----pdf file--------------
iTextSharp.text.pdf.PdfCopy writer2 = new iTextSharp.text.pdf.PdfCopy(doc, myMemoryStream);
doc.Open();
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(imagepath + "/30244.pdf");
reader.ConsolidateNamedDestinations();
for (int i = 1; i <= reader.NumberOfPages; i++) {
iTextSharp.text.pdf.PdfImportedPage page = writer2.GetImportedPage(reader, i);
writer2.AddPage(page);
}
iTextSharp.text.pdf.PRAcroForm form = reader.AcroForm;
if (form != null) {
writer2.CopyAcroForm(reader);
}
//-----------------jpeg file-------------------------------------
MemoryStream myMemoryStream2 = new MemoryStream();
System.Drawing.Image image = System.Drawing.Image.FromFile(imagepath + "/Vouchers.jpg");
iTextSharp.text.Document doc2 = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4);
iTextSharp.text.pdf.PdfWriter.GetInstance(doc2, myMemoryStream2);
doc2.Open();
iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Jpeg);
doc2.Add(pdfImage);
doc2.close();
doc.close();
byte[] content = myMemoryStream.ToArray;
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=LeftCorner568.pdf");
Response.BinaryWrite(content);
既然你在这方面遇到了一段时间的麻烦,现在我要给你一个很长的答案,希望能对你有所帮助。
首先,我无权访问 ASP.Net 服务器,所以我 运行 桌面文件夹中的所有内容。因此,您将看到我从 Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
开始工作,而不是从相对路径读取和写入。我假设您稍后可以交换路径。
其次,(这并不重要)我没有 SSRS,所以我创建了一个辅助方法,它使我可以从 returns 一个 PDF 作为字节数组来制作一个伪造的 PDF :
/// <summary>
/// Create a fake SSRS report
/// </summary>
/// <returns>A valid PDF stored as a byte array</returns>
private Byte[] getSSRSPdfAsByteArray() {
using (var ms = new System.IO.MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.Add(new Paragraph("This is my SSRS report"));
doc.Close();
}
}
return ms.ToArray();
}
}
第三,为了让我们在同一页上并有一些可以使用的东西,我创建了两个额外的辅助方法来生成一些示例图像和 PDF:
/// <summary>
/// Create sample images in the folder provided
/// </summary>
/// <param name="count">The number of images to create</param>
/// <param name="workingFolder">The folder to create images in</param>
private void createSampleImages(int count, string workingFolder) {
var random = new Random();
for (var i = 0; i < count; i++) {
using (var bmp = new System.Drawing.Bitmap(200, 200)) {
using (var g = System.Drawing.Graphics.FromImage(bmp)) {
g.Clear(Color.FromArgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)));
}
bmp.Save(System.IO.Path.Combine(workingFolder, string.Format("Image_{0}.jpg", i)));
}
}
}
/// <summary>
/// Create sample PDFs in the folder provided
/// </summary>
/// <param name="count">The number of PDFs to create</param>
/// <param name="workingFolder">The folder to create PDFs in</param>
private void createSamplePDFs(int count, string workingFolder) {
var random = new Random();
for (var i = 0; i < count; i++) {
using (var ms = new System.IO.MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
var pageCount = random.Next(1, 10);
for (var j = 0; j < pageCount; j++) {
doc.NewPage();
doc.Add(new Paragraph(String.Format("This is page {0} of document {1}", j, i)));
}
doc.Close();
}
}
System.IO.File.WriteAllBytes(System.IO.Path.Combine(workingFolder, string.Format("File_{0}.pdf", i)), ms.ToArray());
}
}
}
重申一下,您显然不需要这三个辅助方法,它们只是为了让您和我有一组共同的文件来处理。这些辅助方法也有意不加注释。
第四,在下面代码的末尾,我将最终的 PDF 存储到一个名为 finalFileBytes
的字节数组中,然后将其写入磁盘。再一次,我在桌面上工作,所以这是你应该做的地方 Response.BinaryWrite(finalFileBytes)
。
第五,合并文件的方式不同。 PdfCopy
、PdfSmartCopy
、PdfStamper
都是常用的。我鼓励您阅读 official iText/iTextSharp book 或至少阅读免费的第 6 章,使用现有 PDF,其中详细介绍了这一点。在下面的代码中,我使用 PdfSmartCopy
并且在导入之前将每个图像转换为 PDF。可能有更好的方法,但我不确定您是否可以一次完成所有操作。布鲁诺会比我更清楚。但下面的作品。
有关正在发生的事情的更多详细信息,请参阅各个代码注释。
//The folder that all of our work will be done in
var workingFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Pdf Test");
//This is the final PDF that we'll create for testing purposes
var finalPDF = System.IO.Path.Combine(workingFolder, "test.pdf");
//Create our working directory if it doesn't exist already
System.IO.Directory.CreateDirectory(workingFolder);
//Create sample PDFs and images
createSampleImages(10, workingFolder);
createSamplePDFs(10, workingFolder);
//Create our sample SSRS PDF byte array
var SSRS_Bytes = getSSRSPdfAsByteArray();
//This variable will eventually hold our combined PDF as a byte array
Byte[] finalFileBytes;
//Write everything to a MemoryStream
using (var finalFile = new System.IO.MemoryStream()) {
//Create a generic Document
using (var doc = new Document()) {
//Use PdfSmartCopy to intelligently merge files
using (var copy = new PdfSmartCopy(doc, finalFile)) {
//Open our document for writing
doc.Open();
//#1 - Import the SSRS report
//Bind a reader to our SSRS report
using (var reader = new PdfReader(SSRS_Bytes)) {
//Loop through each page
for (var i = 1; i <= reader.NumberOfPages; i++) {
//Add the imported page to our final document
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
//#2 - Image the images
//Loop through each image in our working directory
foreach (var f in System.IO.Directory.EnumerateFiles(workingFolder, "*.jpg", SearchOption.TopDirectoryOnly)) {
//There's different ways to do this and it depends on what exactly "add an image to a PDF" really means
//Below we add each individual image to a PDF and then merge that PDF into the main PDF
//This could be optimized greatly
//From https://alandjackson.wordpress.com/2013/09/27/convert-an-image-to-a-pdf-in-c-using-itextsharp/
//Get the size of the current image
iTextSharp.text.Rectangle pageSize = null;
using (var srcImage = new Bitmap(f)) {
pageSize = new iTextSharp.text.Rectangle(0, 0, srcImage.Width, srcImage.Height);
}
//Will eventually hold the PDF with the image as a byte array
Byte[] imageBytes;
//Simple image to PDF
using (var m = new MemoryStream()) {
using (var d = new Document(pageSize, 0, 0, 0, 0)) {
using (var w = PdfWriter.GetInstance(d, m)) {
d.Open();
d.Add(iTextSharp.text.Image.GetInstance(f));
d.Close();
}
}
//Grab the bytes before closing out the stream
imageBytes = m.ToArray();
}
//Now merge using the same merge code as #1
using (var reader = new PdfReader(imageBytes)) {
for (var i = 1; i <= reader.NumberOfPages; i++) {
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
}
//#3 - Merge additional PDF
//Look for each PDF in our working directory
foreach (var f in System.IO.Directory.EnumerateFiles(workingFolder, "*.pdf", SearchOption.TopDirectoryOnly)) {
//Because I'm writing samples files to disk but not cleaning up afterwards
//I want to avoid adding my output file as an input file
if (f == finalPDF) {
continue;
}
//Now merge using the same merge code as #1
using (var reader = new PdfReader(f)) {
for (var i = 1; i <= reader.NumberOfPages; i++) {
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
}
doc.Close();
}
}
//Grab the bytes before closing the stream
finalFileBytes = finalFile.ToArray();
}
//At this point finalFileBytes holds a byte array of a PDF
//that contains the SSRS PDF, the sample images and the
//sample PDFs. For demonstration purposes I'm just writing to
//disk but this could be written to the HTTP stream
//using Response.BinaryWrite()
System.IO.File.WriteAllBytes(finalPDF, finalFileBytes);
磁盘上有两个文件 .jpg 和 .pdf,我需要读取这两个文件并将它们添加到新的 pdf 并发送到浏览器以便可以下载。
新的 pdf 文件仅包含 pdf 内容而不包含 jpeg 文件图像。
memoryStream myMemoryStream = new MemoryStream();
//----pdf file--------------
iTextSharp.text.pdf.PdfCopy writer2 = new iTextSharp.text.pdf.PdfCopy(doc, myMemoryStream);
doc.Open();
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(imagepath + "/30244.pdf");
reader.ConsolidateNamedDestinations();
for (int i = 1; i <= reader.NumberOfPages; i++) {
iTextSharp.text.pdf.PdfImportedPage page = writer2.GetImportedPage(reader, i);
writer2.AddPage(page);
}
iTextSharp.text.pdf.PRAcroForm form = reader.AcroForm;
if (form != null) {
writer2.CopyAcroForm(reader);
}
//-----------------jpeg file-------------------------------------
MemoryStream myMemoryStream2 = new MemoryStream();
System.Drawing.Image image = System.Drawing.Image.FromFile(imagepath + "/Vouchers.jpg");
iTextSharp.text.Document doc2 = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4);
iTextSharp.text.pdf.PdfWriter.GetInstance(doc2, myMemoryStream2);
doc2.Open();
iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(image, System.Drawing.Imaging.ImageFormat.Jpeg);
doc2.Add(pdfImage);
doc2.close();
doc.close();
byte[] content = myMemoryStream.ToArray;
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=LeftCorner568.pdf");
Response.BinaryWrite(content);
既然你在这方面遇到了一段时间的麻烦,现在我要给你一个很长的答案,希望能对你有所帮助。
首先,我无权访问 ASP.Net 服务器,所以我 运行 桌面文件夹中的所有内容。因此,您将看到我从 Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
开始工作,而不是从相对路径读取和写入。我假设您稍后可以交换路径。
其次,(这并不重要)我没有 SSRS,所以我创建了一个辅助方法,它使我可以从 returns 一个 PDF 作为字节数组来制作一个伪造的 PDF :
/// <summary>
/// Create a fake SSRS report
/// </summary>
/// <returns>A valid PDF stored as a byte array</returns>
private Byte[] getSSRSPdfAsByteArray() {
using (var ms = new System.IO.MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
doc.Add(new Paragraph("This is my SSRS report"));
doc.Close();
}
}
return ms.ToArray();
}
}
第三,为了让我们在同一页上并有一些可以使用的东西,我创建了两个额外的辅助方法来生成一些示例图像和 PDF:
/// <summary>
/// Create sample images in the folder provided
/// </summary>
/// <param name="count">The number of images to create</param>
/// <param name="workingFolder">The folder to create images in</param>
private void createSampleImages(int count, string workingFolder) {
var random = new Random();
for (var i = 0; i < count; i++) {
using (var bmp = new System.Drawing.Bitmap(200, 200)) {
using (var g = System.Drawing.Graphics.FromImage(bmp)) {
g.Clear(Color.FromArgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)));
}
bmp.Save(System.IO.Path.Combine(workingFolder, string.Format("Image_{0}.jpg", i)));
}
}
}
/// <summary>
/// Create sample PDFs in the folder provided
/// </summary>
/// <param name="count">The number of PDFs to create</param>
/// <param name="workingFolder">The folder to create PDFs in</param>
private void createSamplePDFs(int count, string workingFolder) {
var random = new Random();
for (var i = 0; i < count; i++) {
using (var ms = new System.IO.MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
var pageCount = random.Next(1, 10);
for (var j = 0; j < pageCount; j++) {
doc.NewPage();
doc.Add(new Paragraph(String.Format("This is page {0} of document {1}", j, i)));
}
doc.Close();
}
}
System.IO.File.WriteAllBytes(System.IO.Path.Combine(workingFolder, string.Format("File_{0}.pdf", i)), ms.ToArray());
}
}
}
重申一下,您显然不需要这三个辅助方法,它们只是为了让您和我有一组共同的文件来处理。这些辅助方法也有意不加注释。
第四,在下面代码的末尾,我将最终的 PDF 存储到一个名为 finalFileBytes
的字节数组中,然后将其写入磁盘。再一次,我在桌面上工作,所以这是你应该做的地方 Response.BinaryWrite(finalFileBytes)
。
第五,合并文件的方式不同。 PdfCopy
、PdfSmartCopy
、PdfStamper
都是常用的。我鼓励您阅读 official iText/iTextSharp book 或至少阅读免费的第 6 章,使用现有 PDF,其中详细介绍了这一点。在下面的代码中,我使用 PdfSmartCopy
并且在导入之前将每个图像转换为 PDF。可能有更好的方法,但我不确定您是否可以一次完成所有操作。布鲁诺会比我更清楚。但下面的作品。
有关正在发生的事情的更多详细信息,请参阅各个代码注释。
//The folder that all of our work will be done in
var workingFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Pdf Test");
//This is the final PDF that we'll create for testing purposes
var finalPDF = System.IO.Path.Combine(workingFolder, "test.pdf");
//Create our working directory if it doesn't exist already
System.IO.Directory.CreateDirectory(workingFolder);
//Create sample PDFs and images
createSampleImages(10, workingFolder);
createSamplePDFs(10, workingFolder);
//Create our sample SSRS PDF byte array
var SSRS_Bytes = getSSRSPdfAsByteArray();
//This variable will eventually hold our combined PDF as a byte array
Byte[] finalFileBytes;
//Write everything to a MemoryStream
using (var finalFile = new System.IO.MemoryStream()) {
//Create a generic Document
using (var doc = new Document()) {
//Use PdfSmartCopy to intelligently merge files
using (var copy = new PdfSmartCopy(doc, finalFile)) {
//Open our document for writing
doc.Open();
//#1 - Import the SSRS report
//Bind a reader to our SSRS report
using (var reader = new PdfReader(SSRS_Bytes)) {
//Loop through each page
for (var i = 1; i <= reader.NumberOfPages; i++) {
//Add the imported page to our final document
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
//#2 - Image the images
//Loop through each image in our working directory
foreach (var f in System.IO.Directory.EnumerateFiles(workingFolder, "*.jpg", SearchOption.TopDirectoryOnly)) {
//There's different ways to do this and it depends on what exactly "add an image to a PDF" really means
//Below we add each individual image to a PDF and then merge that PDF into the main PDF
//This could be optimized greatly
//From https://alandjackson.wordpress.com/2013/09/27/convert-an-image-to-a-pdf-in-c-using-itextsharp/
//Get the size of the current image
iTextSharp.text.Rectangle pageSize = null;
using (var srcImage = new Bitmap(f)) {
pageSize = new iTextSharp.text.Rectangle(0, 0, srcImage.Width, srcImage.Height);
}
//Will eventually hold the PDF with the image as a byte array
Byte[] imageBytes;
//Simple image to PDF
using (var m = new MemoryStream()) {
using (var d = new Document(pageSize, 0, 0, 0, 0)) {
using (var w = PdfWriter.GetInstance(d, m)) {
d.Open();
d.Add(iTextSharp.text.Image.GetInstance(f));
d.Close();
}
}
//Grab the bytes before closing out the stream
imageBytes = m.ToArray();
}
//Now merge using the same merge code as #1
using (var reader = new PdfReader(imageBytes)) {
for (var i = 1; i <= reader.NumberOfPages; i++) {
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
}
//#3 - Merge additional PDF
//Look for each PDF in our working directory
foreach (var f in System.IO.Directory.EnumerateFiles(workingFolder, "*.pdf", SearchOption.TopDirectoryOnly)) {
//Because I'm writing samples files to disk but not cleaning up afterwards
//I want to avoid adding my output file as an input file
if (f == finalPDF) {
continue;
}
//Now merge using the same merge code as #1
using (var reader = new PdfReader(f)) {
for (var i = 1; i <= reader.NumberOfPages; i++) {
copy.AddPage(copy.GetImportedPage(reader, i));
}
}
}
doc.Close();
}
}
//Grab the bytes before closing the stream
finalFileBytes = finalFile.ToArray();
}
//At this point finalFileBytes holds a byte array of a PDF
//that contains the SSRS PDF, the sample images and the
//sample PDFs. For demonstration purposes I'm just writing to
//disk but this could be written to the HTTP stream
//using Response.BinaryWrite()
System.IO.File.WriteAllBytes(finalPDF, finalFileBytes);