带有 Restlet 的 PDFbox

PDFbox with Restlet

我在从我们的 Restlet API.

提供 PDF 文件时遇到问题

我正在使用 Apache PDFBox documentation 中的基本示例代码,它在 Restlet 上下文之外工作正常。

PDDocument document = new PDDocument();

System.err.println("before instantiating new PDPage");
// Create a new blank page and add it to the document
PDPage page = new PDPage(); // LINE FAILING IN RESTLET
System.err.println("after instantiating new PDPage");

document.addPage(page);
document.save("pdf.pdf");
document.close();

这是我在资源中使用 PDFBox 的尝试,最终我想 return 一个 OutputRepresentation 并将 PDDcoument 保存到流中。

以下代码在 PDPage page = new PDPage(); 停止工作,我没有得到任何异常,Restlet 服务器没有 return 任何响应。永远不会打印文本 "after instantiating new PDPage"

编辑:我尽可能地简化了我的代码,但我仍然有问题

这是我的基本路由器:

public class ApiRestletApplication extends Application {

  @Override
  public Restlet createInboundRoot() {
    Router router = new Router(getContext());
    router.attach("/v1/myresource", MyResource.class);
    return router;
  }
}

这是我的资源

public class MyResource extends ServerResource {

  protected static final Logger logger = LoggerFactory.getLogger(MyResource.class);

  @Get
  public Representation toPDF() {

    PDDocument document = new PDDocument();
    System.err.println("before instantiating new PDPage");
    PDPage page = new PDPage();
    System.err.println("after instantiating new PDPage"); //<= never printed
    document.addPage(page);

    return new PDFRepresentation(document);
  }
}

这是我的web.xml

<!-- Restlet application -->
<context-param>
  <param-name>org.restlet.application</param-name>
  <param-value>com.xxx.api.ApiRestletApplication</param-value>
</context-param>

<!-- Restlet adapter -->
<servlet>
  <servlet-name>RestletServlet</servlet-name>
  <servlet-class>
    org.restlet.ext.servlet.ServerServlet
  </servlet-class>
</servlet>

<!-- Catch all requests -->
<servlet-mapping>
  <servlet-name>RestletServlet</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

如果我注释掉符合 PDPage 声明的行和 return 一些 StringRepresentation,一切正常。我可以提供一些 Json、xml 和 excel。但是这个 PDF 快把我逼疯了。

这是我使用的版本:

[INFO] +- org.restlet.jee:org.restlet:jar:2.2.1:compile
[INFO] +- org.restlet.jee:org.restlet.ext.crypto:jar:2.2.1:compile
[INFO] +- org.restlet.jee:org.restlet.ext.servlet:jar:2.2.1:compile

[INFO] |  +- org.apache.pdfbox:pdfbox:jar:1.8.10:compile
[INFO] |  |  +- org.apache.pdfbox:fontbox:jar:1.8.10:compile
[INFO] |  |  \- org.apache.pdfbox:jempbox:jar:1.8.10:compile
[INFO] |  \- com.sun:tools:jar:jdk:system

这是 curl 请求:

curl "http://localhost:8889/v1/myresource" -H "Content-Type: application/pdf" -H "Accept: application/pdf"

这是 eclipse 中的日志:

2015-09-21 15:08:15.933:INFO::Started SelectChannelConnector@0.0.0.0:8889
2015-09-21 15:08:20.698:INFO:/:RestletServlet: [Restlet] Attaching application: com.xxx.api.ApiRestletApplication@2613622c to URI: 
before instantiating new PDPage
//then nothing

感谢您的帮助。

编辑 2:以下代码有效,但我仍然不知道为什么我的代码无效:

public class RestletServerTest extends Application {

  @Override
  public Restlet createInboundRoot() {
    Router router = new Router(getContext());
    router.attach("/v1/myresource", MyResource.class);
    return router;
  }

  public static void main(String[] args) throws Exception {
    Component component = new Component();
    component.getServers().add(Protocol.HTTP, 8182);

    component.getDefaultHost().attach("", new RestletServerTest());
    component.start();
  }
}

编辑 3:问题似乎与 Restlet 无关,而与 PDFBox 和 servlet 相关:PDFBox: Unable to save pdf while running on tomcat

编辑 4:这是解决方案

事实上,您永远不会 return 在响应中包含您创建的 PDF 的内容。您的注释方法的 returned 表示对应于响应内容。

在你的情况下,它应该对应于二进制。您还可以利用内容配置 header 在浏览器中触发下载对话框。

您可以尝试将此内容放入一个字节数组中,然后使用专用表示(例如基于 OuputStream 的表示)通过 Restlet 发送它。

希望对您有所帮助。 蒂埃里

我试过你的示例代码,它对我有用。

我刚刚设置了一个 class 包装 PDDocument 的 PDDocumentRepresentation:

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.restlet.data.MediaType;
import org.restlet.representation.OutputRepresentation;

public class PDDocumentRepresentation extends OutputRepresentation {

    private PDDocument document = new PDDocument();

    public PDDocumentRepresentation(PDDocument document) {
        super(MediaType.APPLICATION_PDF);
        this.document = document;
    }

    @Override
    public void write(OutputStream outputStream) throws IOException {
        try {
            document.save(outputStream);
            document.close();
        } catch (COSVisitorException e) {
            throw new IOException(e);
        }
    }
}

资源代码如下:

public class MyResource extends ServerResource {

    @Get
    public Representation getPdf() {
        PDDocument document = new PDDocument();
        PDPage page = new PDPage();
        document.addPage(page);

        return new PDDocumentRepresentation(document);
    }
}

问题来自 PDFBox 版本。如果我使用 2.0.0-SNAPSHOT (http://pdfbox.apache.org/2.0/getting-started.html) 版本,我可以通过 servlet 生成 PDF。感谢您的帮助。