在 iTextSharp 中更改 PDF 文档的顺序页面
Change order pages of PDF document in iTextSharp
我正在尝试更改我的 PDF 文档的重新排序页面,但我不能,我也不知道为什么。
我读了几篇关于更改顺序的文章,它是 java(iText),我几乎没有遇到什么问题。(exampl1, exampl2, example3). This example on c#, but there is using other method(exampl4)
我想把我的目录放在第 12 页,然后放到第 2 页。在第 12 页之后我还有其他内容。这是我的页面更改顺序模板:
String.Format("1,%s, 2-%s, %s-%s", toc, toc-1, toc+1, n)
这是我更改页面顺序的方法:
public void ChangePageOrder(string path)
{
MemoryStream baos = new MemoryStream();
PdfReader sourcePDFReader = new PdfReader(path);
int toc = 12;
int n = sourcePDFReader.NumberOfPages;
sourcePDFReader.SelectPages(String.Format("1,%s, 2-%s, %s-%s", toc, toc-1, toc+1, n));
using (var fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
{
PdfStamper stamper = new PdfStamper(sourcePDFReader, fs);
stamper.Close();
}
}
这里是对方法的调用:
...
doc.Close();
ChangePageOrder(filePath);
我哪里做错了?
谢谢。
无需详细说明您应该做什么,您可以遍历 pdf 中的所有页面,将它们放入包含所有页面的新 pdf 文档中。您可以将您的逻辑放在 for 循环中。
reader = new PdfReader(sourcePDFpath);
sourceDocument = new Document(reader.GetPageSizeWithRotation(startpage));
pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPDFpath, System.IO.FileMode.Create));
sourceDocument.Open();
for (int i = startpage; i <= endpage; i++)
{
importedPage = pdfCopyProvider.GetImportedPage(reader, i);
pdfCopyProvider.AddPage(importedPage);
}
sourceDocument.Close();
reader.Close();
您的代码无法运行,因为您正在使用 path
创建 PdfReader
以及创建 FileStream
。您可能会收到诸如 "The file is in use" 或 "The file can't be accessed".
之类的错误
这里有解释:
- Whosebug:How to update a PDF without creating a new PDF?
- 官网:
How to update a PDF without creating a new PDF?
您创建了一个名为 baos
的 MemoryStream()
,但您没有在任何地方使用该对象。解决问题的一种方法是,在您首次创建 PDF 时用 MemoryStream
替换 FileStream
,然后使用存储在该内存流中的字节创建一个 PdfReader
实例。在这种情况下,PdfStamper
不会写入正在使用的文件。
另一种选择是使用不同的 path
。例如:首先将文档写入名为 my_story_unordered.pdf
的文件(由 PdfWriter
创建),然后将文档写入名为 my_story_reordered.pdf
的文件(由 PdfStamper
创建) .
也可以一次创建最终文档。在这种情况下,您需要切换到线性模式。我的书 "iText in Action - Second Edition" 中有一个示例展示了如何执行此操作:MovieHistory1
在此示例的 C# 端口中,您有:
writer.SetLinearPageMode();
一般情况下,iText会创建一个有枝有叶的页面树。一旦一个分支的叶子超过 10 个,就会创建一个新分支。使用 setLinearPageMode()
,您告诉 iText 不要这样做。完整的页面树将由一个只有叶子的分支组成(没有额外的分支)。从查看文档时的性能角度来看,这很糟糕,但如果文档中的页数有限,这是可以接受的。
切换到页面模式后,您可以像这样重新排序页面:
document.NewPage();
// get the total number of pages that needs to be reordered
int total = writer.ReorderPages(null);
// change the order
int[] order = new int[total];
for (int i = 0; i < total; i++) {
order[i] = i + toc;
if (order[i] > total) {
order[i] -= total;
}
}
// apply the new order
writer.ReorderPages(order);
总结:如果您的文档页数不多,请使用ReorderPages
方法。如果您的文档有很多页,请使用您一直在尝试的方法,但要正确地进行。不要尝试写入您仍在尝试读取的文件。
我正在尝试更改我的 PDF 文档的重新排序页面,但我不能,我也不知道为什么。
我读了几篇关于更改顺序的文章,它是 java(iText),我几乎没有遇到什么问题。(exampl1, exampl2, example3). This example on c#, but there is using other method(exampl4)
我想把我的目录放在第 12 页,然后放到第 2 页。在第 12 页之后我还有其他内容。这是我的页面更改顺序模板:
String.Format("1,%s, 2-%s, %s-%s", toc, toc-1, toc+1, n)
这是我更改页面顺序的方法:
public void ChangePageOrder(string path)
{
MemoryStream baos = new MemoryStream();
PdfReader sourcePDFReader = new PdfReader(path);
int toc = 12;
int n = sourcePDFReader.NumberOfPages;
sourcePDFReader.SelectPages(String.Format("1,%s, 2-%s, %s-%s", toc, toc-1, toc+1, n));
using (var fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
{
PdfStamper stamper = new PdfStamper(sourcePDFReader, fs);
stamper.Close();
}
}
这里是对方法的调用:
...
doc.Close();
ChangePageOrder(filePath);
我哪里做错了?
谢谢。
无需详细说明您应该做什么,您可以遍历 pdf 中的所有页面,将它们放入包含所有页面的新 pdf 文档中。您可以将您的逻辑放在 for 循环中。
reader = new PdfReader(sourcePDFpath);
sourceDocument = new Document(reader.GetPageSizeWithRotation(startpage));
pdfCopyProvider = new PdfCopy(sourceDocument, new System.IO.FileStream(outputPDFpath, System.IO.FileMode.Create));
sourceDocument.Open();
for (int i = startpage; i <= endpage; i++)
{
importedPage = pdfCopyProvider.GetImportedPage(reader, i);
pdfCopyProvider.AddPage(importedPage);
}
sourceDocument.Close();
reader.Close();
您的代码无法运行,因为您正在使用 path
创建 PdfReader
以及创建 FileStream
。您可能会收到诸如 "The file is in use" 或 "The file can't be accessed".
这里有解释:
- Whosebug:How to update a PDF without creating a new PDF?
- 官网: How to update a PDF without creating a new PDF?
您创建了一个名为 baos
的 MemoryStream()
,但您没有在任何地方使用该对象。解决问题的一种方法是,在您首次创建 PDF 时用 MemoryStream
替换 FileStream
,然后使用存储在该内存流中的字节创建一个 PdfReader
实例。在这种情况下,PdfStamper
不会写入正在使用的文件。
另一种选择是使用不同的 path
。例如:首先将文档写入名为 my_story_unordered.pdf
的文件(由 PdfWriter
创建),然后将文档写入名为 my_story_reordered.pdf
的文件(由 PdfStamper
创建) .
也可以一次创建最终文档。在这种情况下,您需要切换到线性模式。我的书 "iText in Action - Second Edition" 中有一个示例展示了如何执行此操作:MovieHistory1
在此示例的 C# 端口中,您有:
writer.SetLinearPageMode();
一般情况下,iText会创建一个有枝有叶的页面树。一旦一个分支的叶子超过 10 个,就会创建一个新分支。使用 setLinearPageMode()
,您告诉 iText 不要这样做。完整的页面树将由一个只有叶子的分支组成(没有额外的分支)。从查看文档时的性能角度来看,这很糟糕,但如果文档中的页数有限,这是可以接受的。
切换到页面模式后,您可以像这样重新排序页面:
document.NewPage();
// get the total number of pages that needs to be reordered
int total = writer.ReorderPages(null);
// change the order
int[] order = new int[total];
for (int i = 0; i < total; i++) {
order[i] = i + toc;
if (order[i] > total) {
order[i] -= total;
}
}
// apply the new order
writer.ReorderPages(order);
总结:如果您的文档页数不多,请使用ReorderPages
方法。如果您的文档有很多页,请使用您一直在尝试的方法,但要正确地进行。不要尝试写入您仍在尝试读取的文件。