itext pdf 合并会翻转方向的问题. 修复方法.
itext pdf 在处理合并多个页面的时候.
有两种方法
一种是直接用itext 的Write 控制输出.
另外一种方法是使用 PdfCopy 类进行复制..
自己用Write控制还算可以.一般都是下面这样写.
public static MemoryStream mergePDFStream(MemoryStream[] files, iTextSharp.text.Rectangle pagesize = null)
{
//outMergeFile = Server.MapPath(outMergeFile);
//if (outMergeFile == null)
//{
// outMergeFile = "d:\\" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + new Random().Next(1000) + ".pdf";
//}
PdfReader reader;
Document document;
if (pagesize == null)
{
document = new Document();
//pagesize = PageSize.A4;
}
else
{
document = new Document(pagesize);
}
//var fs = new FileStream(outMergeFile, FileMode.Create);
MemoryStream fs = new MemoryStream();
//BufferedStream bfs = new BufferedStream(fs);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
writer.CloseStream = false; //不自动关闭内存流.
document.Open();
PdfContentByte cb = writer.DirectContent;
for (int i = 0; i < files.Length; i++)
{
reader = new PdfReader(files[i].ToArray());
//关闭内存流.
files[i].Close();
int iPageNum = reader.NumberOfPages;
for (int j = 1; j <= iPageNum; j++)
{
PdfImportedPage newPage = writer.GetImportedPage(reader, j);
//cb.Add(newPage);
//cb.MoveTo(0, 0);
// PageSize.A4.Height - newPage.Height 解决itext 高度的问题. itext 的y 轴默认是从下面开始
if (pagesize == null)
{
// newPage.Height;
var newPageSize = new iTextSharp.text.Rectangle(newPage.Width, newPage.Height);
document.SetPageSize(newPageSize); //这句话使得每页都跟原纸张大小一致.
document.NewPage();
cb.AddTemplate(newPage, 0, 0);
}
else
{
document.SetPageSize(pagesize);
document.NewPage();
cb.AddTemplate(newPage, 0, pagesize.Height - newPage.Height); //- newPage.Height 解决itext 高度的问题. itext 的y 轴默认是从下面开始 减的目的是使其向上对齐.
//cb.AddTemplate(newPage, 1f, 0, 0, 1f, 0, pagesize.Height);
// case 0:
// writer.DirectContent.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
// break;
//case 90:
// writer.DirectContent.AddTemplate(importedPage, 0, -1f, 1f, 0, 0, pageHeight);
// break;
//case 180:
// writer.DirectContent.AddTemplate(importedPage, -1f, 0, 0, -1f, pageWidth, pageHeight);
// break;
//case 270:
// writer.DirectContent.AddTemplate(importedPage, 0, 1f, -1f, 0, pageWidth, 0);
// break;
// default:
}
}
//reader.Close();
}
document.Close();
//byte[] fileBuffer = fs.GetBuffer();
return fs;
}
但是上面的这个方法是有问题的. 无论怎么改都不能解决翻转问题. 估计是
cb.AddTemplate(newPage, 0, pagesize.Height - newPage.Height);
没用对, 后面再研究.
第二种使用PdfCopy的方法一般都是下面这样写的.
public static PdfMemoryStream mergePDFFiles(string[] fileList)
{
//outMergeFile = Server.MapPath(outMergeFile);
//if (outMergeFile == null)
//{
// outMergeFile = "d:\\" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + new Random().Next(1000) + ".pdf";
//}
PdfReader reader = null;
Document document = new Document();
PdfMemoryStream fs = new PdfMemoryStream();
fs.AllowClose = false;
PdfCopy p = new PdfSmartCopy(document, fs); // 生成的目标PDF文件
document.Open();
for (int i = 0; i < fileList.Length; i++)
{
try
{
//var fs = new FileStream(outMergeFile, FileMode.Create);
reader = new PdfReader(fileList[i]); // 读取源文件
int n = reader.NumberOfPages; // 获取源文件的页数
PdfDictionary pd;
for (int j = 1; j <= n; j++)
{
pd = reader.GetPageN(j);
//pd.Put(PdfName.ROTATE, new PdfNumber(90)); // 顺时针旋转90°
}
for (int page = 0; page < n; )
{
p.AddPage(p.GetImportedPage(reader, ++page));
}
reader.Close();//这里需要关闭. 否则会占着文件不释放.
}
catch (Exception ex)
{
throw new Exception("打开原始PDF文档失败,文件路径为:" + fileList[i], ex);
}
}
document.Close();
//byte[] fileBuffer = fs.GetBuffer();
return fs;
}
这第二种方法也是不行的..经过很长时间的猜测和实验, 发现这种方法也是解决不了问题的….从A5变成A4的时候总是会翻转掉….
经过4天的苦战和尝试, 最后终于搞定了.
我这种方法只适合目标大小确定的情况. 如果目标大小不确定的, 还需要再考虑其它方法
/// 合併PDF檔(集合)改进版,不会翻转内容
/// 欲合併PDF檔之集合(一筆以上)
/// 纸张大小
/// 报告单上的logo
public static MemoryStream mergePDFStream(Stream[] files, iTextSharp.text.Rectangle pagesize = null, LogoImgConfig logo = null)
{
Document document;
if (pagesize == null)
{
document = new Document();
//pagesize = PageSize.A4;
}
else
{
document = new Document(pagesize);
}
//var fs = new FileStream(outMergeFile, FileMode.Create);
PdfMemoryStream fs = new PdfMemoryStream();
fs.AllowClose = false;
//PdfCopy pcopy = new PdfSmartCopy(document, fs); // 生成的目标PDF文件
//pcopy.ChangePageSize(pagesize);
PdfWriter write = PdfWriter.GetInstance(document, fs);
write.CloseStream = false; //不自动关闭内存流.
document.Open();
//document.NewPage();
PdfContentByte cb = write.DirectContent;
for (int i = 0; i < files.Length; i++)
{
try
{
//File.AppendAllText("d:\\ttt.txt", "***** 开始处理第" + i + "个文件******\r\n");
//var fs = new FileStream(outMergeFile, FileMode.Create);
PdfReader reader = new PdfReader(files[i]); // 读取源文件
//var pdfVersion = reader.PdfVersion;
//var pdfVersion = reader.PdfVersion;
//PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
//PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
//reader.get
//var v = reader.Catalog.Get(PdfName.VERSION);
iTextSharp.text.Image logoimg = null;
/*增加LOGO图片.*/
if (logo != null)
{
//newPage.AddImage();
//创建一个logo图片对象
logoimg = iTextSharp.text.Image.GetInstance(logo.ImgUri);
//logoimg.BackgroundColor = BaseColor.RED;
//logoimg.Border = 1;
//logoimg.BorderColor = BaseColor.RED;
logoimg.ScaleToFit(new iTextSharp.text.Rectangle(logo.Width, logo.Height));
//设置图片的指定大小
//img.ScaleToFit(140F, 320F);
//img.Rotation = rotation;
//按比例缩放
//img.ScalePercent(50);
// logoimg.PlainHeight == logo.Height 是一样的.
logoimg.SetAbsolutePosition(logo.Left, pagesize.Height - logo.Height - logo.Top);//y轴的原点在左下角.
}
//img.Width = 50;
//img.SetAbsolutePosition(10, 20);
//img.Rotation = 270;
//write.DirectContent.AddImage(img);
int n = reader.NumberOfPages; // 获取源文件的页数
for (int pageIndex = 1; pageIndex <= n; pageIndex++)
{
// var Rotation = reader.GetPageRotation(pageIndex);
//var pd = reader.GetPageN(pageIndex);
//pd.Put(PdfName.ROTATE, new PdfNumber(90)); //先修改参数内容, 后面再GetImportedPage
var newPage = write.GetImportedPage(reader, pageIndex);
//if (pdfVersion <= '3') //1.3版 或者以前的版本 坐标系统是不一样的.要旋转90度.
//if (newPage.Height == pagesize.Width) //这种写法容错性比较差会有小数部分 改成下面的.
//如果老的纸张高度等于目标纸张的宽度,那么直接旋转90度. 例如A5的高度 等于A4的宽度.
//
if (Math.Abs(newPage.Height - pagesize.Width) < 5)
{
document.NewPage();
document.SetPageSize(pagesize); //这句话使得每页都跟原纸张大小一致.
cb.AddTemplate(newPage, 0, -1, 1, 0, 0, pagesize.Height, true, true);// 0,-1,1,0, 用来旋转pdf内容
// 把图片增加到内容页的指定位子 b width c height e bottom f left
// cb.AddImage(img, 0, 32F, 32F, 0, 50F, 20);
//write.DirectContent.AddImage(img); //添加图片
}
else //4,5,6,7
{
document.NewPage();
document.SetPageSize(pagesize); //这句话使得每页都跟原纸张大小一致.
cb.AddTemplate(newPage, 0, pagesize.Height - newPage.Height);
// 把图片增加到内容页的指定位子 b width c height e bottom f left
//write.DirectContent.AddImage(img); //添加图片
}
// 把图片增加到内容页的指定位子 b width c height e bottom f left
//cb.AddImage(img, 0, 100, 100, 0, 10, 10);
if (logo != null)
{ //这个添加图片必须在复制完页面的下面.
cb.AddImage(logoimg);
}
}
logoimg = null;
//reader.Close();//这里需要关闭. 否则会占着文件不释放.
}
catch (Exception ex)
{
throw new Exception("解析原始PDF文档失败,文件路径为:" + files[i], ex);
}
}
if (document.IsOpen())
{
document.Close();
}
//fs.Close();
//byte[] fileBuffer = fs.GetBuffer();
fs.Position = 0; //使指针指向第一位.
return fs;
}