当前位置: 首页 > 知识库问答 >
问题:

iText 2.1.7 找不到页面引用?

夏飞掣
2023-03-14

我正在维护一个使用iText 2.1.7创建PDF的web应用程序。我想获取现有PDF的内容,并将其放入PDF文档中,代码正在创建中。我有以下(编辑:更完整的代码):

package itexttest;

import com.lowagie.text.Document;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

public class ITextTest 
{
    public static void main(String[] args) 
    {
        try
        {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Document bigDoc = new Document(PageSize.LETTER, 50, 50, 110, 60);
            PdfWriter writer = PdfWriter.getInstance(bigDoc, os);
            bigDoc.open();

            Paragraph par = new Paragraph("one");
            bigDoc.add(par);
            bigDoc.add(new Paragraph("three"));

            addPdfPage(bigDoc, os, "c:/insertable.pdf");

            bigDoc.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private static void addPdfPage(Document document, OutputStream outputStream, String location) {
        try {

            PdfReader pdfReader = new PdfReader(location);
            int pages = pdfReader.getNumberOfPages();

            PdfCopy pdfCopy = new PdfCopy(document, outputStream);
            PdfImportedPage page = pdfCopy.getImportedPage(pdfReader, 1);
            pdfCopy.addPage(page);
        }
        catch (Exception e) {
            System.out.println("Cannot add PDF from PSC: <" + location + ">: " + e.getMessage());
            e.printStackTrace();
        }
    }

}

这将引发一个错误,空值来自

我怎么用错了?如何从现有文档中获取一个页面并放入当前文档中?请注意,我并不是在一个可以方便地将文件作为临时存储或其他东西写入的地方。

共有2个答案

饶曦之
2023-03-14

这是另一个版本,包含mkl的更正,希望这些名称能够用于其他问题:

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;

public class PdfPlay
{
      public static void main(String[] args) 
      {
          try
          {
              ByteArrayOutputStream outputStream1 = new ByteArrayOutputStream();

              Document document1 = new Document(PageSize.LETTER, 50, 50, 110, 60);
              PdfWriter writer1 = PdfWriter.getInstance(document1, outputStream1);

              document1.open();
              document1.add(new Paragraph("one"));
              document1.add(new Paragraph("two"));
              document1.add(new Paragraph("three"));
              document1.close();

              byte[] withInsert = addPdfPage(outputStream1, "insertable.pdf");

          }
          catch (Exception e)
          {
              e.printStackTrace();
          }
      }

      private static byte[] addPdfPage(ByteArrayOutputStream outputStream1, String insertFilename) 
      {
          try 
          {
            ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
            Document document2 = new Document();
            PdfCopy copy = new PdfCopy(document2, new FileOutputStream("inserted.pdf"));
            document2.open();
            PdfReader outputStream1Reader = new PdfReader(outputStream1.toByteArray());
            for (int i=1; i<=outputStream1Reader.getNumberOfPages(); i++)
            {
              copy.addPage(copy.getImportedPage(outputStream1Reader, i));
            }
            PdfReader insertReader = new PdfReader(insertFilename);
            copy.addPage(copy.getImportedPage(insertReader, 1));

            document2.close();
            outputStream1Reader.close();
            insertReader.close();

            byte[] result = outputStream2.toByteArray();
            return result;
          }
          catch (Exception e) 
          {
              System.out.println("Cannot add PDF from PSC: <" + insertFilename + ">: " + e.getMessage());
              e.printStackTrace();
              return null;
          }
      }

}

如果在程序的默认目录中使用文件“可插入.pdf”运行,则此程序将在同一目录中生成文件“插入.pdf”,第一页上有文本行“一”,“二”和“三”,第二页上有“可插入.pdf”的第一页。

所以mkl的修正是有效的;为了在我想使用它的环境中使用它,有几个问题:

我有一个程序,我想在其中使用这个功能,它是一个web应用程序,因此没有现成的访问权限来写入文件。我假设我可以使用ByteArrayOutputStream来代替这里的输出文件。

是否绝对有必要创建新的输出流才能插入内容?我希望有一种方法可以告诉一些iText组件“这是一个文件;阅读它的第一页,并将其插入到文档/输出流/作家中,我已经打开了。内存中的PDF文档可能会变得相当大;我宁愿不必复制所有现有的PDF结构,这样我就可以向它们添加另一个。如果我最终插入来自多个其他文档的页面,我可能不得不多次这样做,我想......

严峰
2023-03-14

我不再积极使用旧的iText版本,但从那时起,有些事情就没有改变过。因此,代码和指针中的一些问题有助于解决这些问题:

您当前代码中的主要问题是您

>

  • PdfWriter重用Document实例(您已经在PdfWriter中使用并且已经打开)用于PdfCopy;虽然Document可以支持多个侦听器,但它们都需要在调用open之前进行注册;此构造的用例是以两种不同的格式并行创建相同的文档;并且您

    为您的< code>PdfWriter和< code>PdfCopy使用相同的输出流;结果不是一个有效的PDF,而是两个不同PDF的字节范围混合在一起,也就是说,肯定不是一个有效的PDF。

    您可以先创建一个新的PDF,其中包含< code > ByteArrayOutputStream 中的新段落(关闭所涉及的< code >文档),然后将此PDF和您想要添加的其他页面复制到新的PDF中,从而重新构建您的代码。

    比如像这样:

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    Document bigDoc = new Document(PageSize.LETTER, 50, 50, 110, 60);
    PdfWriter writer = PdfWriter.getInstance(bigDoc, os);
    bigDoc.open();
    Paragraph par = new Paragraph("one");
    bigDoc.add(par);
    bigDoc.add(new Paragraph("three"));
    bigDoc.close();
    
    ByteArrayOutputStream os2 = new ByteArrayOutputStream();
    Document finalDoc = new Document();
    PdfCopy copy = new PdfCopy(finalDoc, new FileOutputStream(RESULT2));
    finalDoc.open();
    PdfReader reader = new PdfReader(os.toByteArray());
    for (int i = 0; i < reader.getNumberOfPages();) {
        copy.addPage(copy.getImportedPage(reader, ++i));
    }
    PdfReader pdfReader = new PdfReader("c:/insertable.pdf");
    copy.addPage(copy.getImportedPage(pdfReader, 1));
    finalDoc.close();
    reader.close();
    pdfReader.close();
    
    // result PDF
    byte[] result = os2.toByteArray();           
    

    您也可以通过直接将页面导入PdfWriter来更改代码,例如:

    ByteArrayOutputStream os = new ByteArrayOutputStream();
    Document bigDoc = new Document(PageSize.LETTER, 50, 50, 110, 60);
    PdfWriter writer = PdfWriter.getInstance(bigDoc, os);
    bigDoc.open();
    Paragraph par = new Paragraph("one");
    bigDoc.add(par);
    bigDoc.add(new Paragraph("three"));
    
    PdfReader pdfReader = new PdfReader("c:/insertable.pdf");
    PdfImportedPage page = writer.getImportedPage(pdfReader, 1);
    bigDoc.newPage();
    PdfContentByte canvas = writer.getDirectContent();
    canvas.addTemplate(page, 1, 0, 0, 1, 0, 0);
    
    bigDoc.close();
    pdfReader.close();
    
    // result PDF
    byte[] result = os.toByteArray();           
    

    这种方法似乎更好,因为不需要中间的PDF。不幸的是,这种外观是欺骗性的,这种方法作为一些缺点。

    这里不是将整个原始页面按原样复制和添加到文档中,而是仅将其内容流用作模板的内容,然后从实际的新文档页面中引用该模板。这尤其意味着:

    > < li>

    如果导入页面的尺寸与您的新目标文档不同,它的某些部分可能会被剪切掉,而新页面的某些部分会保持空白。因此,您经常会发现上面代码的变体,通过缩放和旋转来尝试使导入的页面和目标页面相适应。

    原始页面内容现在位于新页面引用的模板中。如果您使用相同的机制将这个新页面导入到另一个文档中,您会得到一个引用模板的页面,而这个模板又仅仅引用了一个包含原始内容的模板。如果您将这个页面导入到另一个文档中,您将获得另一个层次的间接性。等等。等等..

    不幸的是,符合标准的PDF查看器只需要在有限的程度上支持这种间接性。如果您继续此过程,您的页面内容可能会突然看不到了。如果原始页面已经带来了它自己的引用模板的层次结构,这可能会早些发生。

    由于只复制内容,不在内容流中的原始页面的属性将会丢失。这尤其涉及到像表单域或某些类型的高亮标记甚至某些类型的自由文本这样的注释。

    (顺便说一下,这些模板在通用PDF规范行话中被称为Form XObjects。)

    此答案明确涉及在合并PDF的上下文中使用PdfCopyPdfWriter

  •  类似资料:
    • 我有以下错误 未找到页面(404)请求方法:GET请求URL:http://127.0.0.1:8000/使用Decoder.urls中定义的URLconf,Django尝试了这些URL模式,顺序如下:form.html[name='form1']hl7[name='hl7']空路径与这些都不匹配。您会看到这个错误,因为您的Django设置文件中有DEBUG=True。将其更改为False,Dja

    • 问题内容: 我有一个应用程序,它使用一个ng-view和多个控制器和视图。如果我浏览根目录,例如:www.domain.com,则一切正常。除非我按Ctrl +R(刷新),否则会显示404错误页面未找到。例如:刷新此页面给我错误。http://domain.com/item/1/。 但是,如果我使用hashbang访问页面,则它可以工作。例如:http://domain.com/#!/item/1

    • 我试图用包含jsp和@Controller的Spring MVC启动Jetty。在启动jetty之后,如果我试图调用任何页面,我会得到每次警告。例如: TTP://localhost:8080/GetMessageStats/ 在名为“org.springframework.web.servlet.DispatcherServlet”的DispatcherServlet中找不到URI为[/reso

    • 我在服务器上上传了我的网站,我的网站运行良好。但我有个问题。 当我从路由转到路由时,组件也被加载了。但是当我复制我的组件url时,我得到了。 例如,当我复制/粘贴此url时: http://test.shadyab.com/offers/Arya-Ceremonial-Pool-VIP-off 我有一个。 我的路线: 我的应用程序。js: 即使用户想要刷新当前网页,也会收到404错误。 我的服务器

    • 我还添加了我的pom.xml 我创建了一个responseBody,然后Spring找到了上面写的内容。但当我试图找到一页时,Spring却找不到。Spring正在映射我的类..

    • 当我使用eclipse启动Tomcat9,然后导航到http://localhost:8080时,它会给出404页的not found并抛出错误:“origin server dot find a current representation for the target resource or is not welligen to display that ixist”。但是,当我转到tomca