1

編集:以下の回答で私の作業コードを参照してください。


簡単に言うと、Java Bean のメソッドを呼び出す JSP ファイルがあります。このメソッドは PDF ファイルを作成し、理論的にはそれを JSP に返し、ユーザーがダウンロードできるようにします。ただし、PDF をロードすると、Adobe Reader は次のエラーを返します:ファイルは '%PDF-' で始まりません

詳細:これまでのところ、JSP はメソッドを正常に呼び出し、PDF が作成され、JSP がユーザーに完成した PDF ファイルを提供するように見えます。ただし、Adobe Reader が PDF ファイルを開こうとすると、すぐにエラーが表示されます:ファイルが '%PDF-' で始まっていません。念のため、方法でデスクトップに PDF を作成して確認できるようにします。Windows内で通常どおり開くと、正常に表示されます。では、JSP からの出力が異なるのはなぜでしょうか。

PDF を作成するために、Apache FOPを使用しています。私は彼らの最も基本的な例の 1 つに従っていますが、結果の PDF を単純にローカル マシンに保存するのではなく、JSP に渡すことを除きます。私は彼らの基本的な使用パターンこのコード例に従っています。

これが私のJSPファイルです:

<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>

<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.printreports.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>

<c:set scope="page" var="xml" value="${printReportsBean.download}"/>

これが私の Java Bean メソッドです。

//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();

public File getDownload() throws UtilException {

    OutputStream out = null;
    File pdf = new File("C:\\documents and settings\\me\\Desktop\\HelloWorld.pdf");
    File fo  = new File("C:\\somedirectory", "HelloWorld.fo");

    try {

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        out = new FileOutputStream(pdf);
        out = new BufferedOutputStream(out);

        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(); //identity transformer

        Source src = new StreamSource(fo);

        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(src, res);

        return pdf;

    } catch (Exception e) {

         throw new UtilException("Could not get download. Msg = "+e.getMessage());

    } finally {

         try {
             out.close();
         } catch (IOException io) {
             throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
         }
    }
}

これは非常に具体的な問題であることは承知していますが、どんな助けでも大歓迎です!

4

4 に答える 4

4

わかりました、これは機能しました。これが私がそれをした方法です:

JSP:

<%@ taglib uri="utilTLD" prefix="util" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ page language="java" session="false" %>
<%@ page contentType="application/pdf" %>

<%-- Construct and initialise the PrintReportsBean --%>
<jsp:useBean id="printReportsBean" scope="request" class="some.package.PrintReportsBean" />
<jsp:setProperty name="printReportsBean" property="*"/>

<%
    // get report format as input parameter     
    ServletOutputStream servletOutputStream = response.getOutputStream();

    // reset buffer to remove any initial spaces
    response.resetBuffer(); 

    response.setHeader("Content-disposition", "attachment; filename=HelloWorld.pdf");

    // check that user is authorised to download product
    printReportsBean.getDownload(servletOutputStream);
%>

Java Beanメソッド:

//earlier in the class...
private static FopFactory fopFactory = FopFactory.newInstance();

public void getDownload(ServletOutputStream servletOutputStream) throws UtilException {

    OutputStream outputStream = null;

    File fo  = new File("C:\\some\\path", "HelloWorld.fo");

    try {

        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        outputStream = new BufferedOutputStream(servletOutputStream);

        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outputStream);

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(); //identity transformer

        Source src = new StreamSource(fo);

        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(src, res);

    } catch (Exception e) {

        throw new UtilException("Could not get download. Msg = "+e.getMessage());

    } finally {

        try {
            outputStream.close();
        } catch (IOException io) {
            throw new UtilException("Could not close OutputStream. Msg = "+io.getMessage());
        }
     }
 }

皆様からのご意見ありがとうございました!

于 2008-10-21T09:08:10.213 に答える
4

私が過去にこのタイプの機能を実装した方法は、サーブレットが PDF ファイルの内容をストリームとして応答に書き出すようにすることでした。私はもうソース コードを持っていません (そして、サーブレット/jsp の作業を行ってから少なくとも 1 年は経ちます) が、試してみたいことは次のとおりです。

サーブレットで、応答の出力ストリームのハンドルを取得します。応答の MIME タイプを「application/pdf」に変更し、例にあるファイル処理をサーブレットに実行させます。File オブジェクトを返す代わりに、サーブレットでファイルを出力ストリームに書き込むだけです。ファイル I/O の例を参照し、 outfile.write(...) 行を responseStream.write(...) に置き換えるだけで、準備完了です。出力ストリームをフラッシュして閉じ、リターンを行うと、記憶が正しければ、ブラウザーは応答から pdf を取得できるはずです。

于 2008-10-20T16:02:52.373 に答える
3

推測ですが、JSP ページが返す MIME タイプを確認しましたか?

編集:あなたが投稿したコードを実際に読んだら、あなたがそれを設定したことがわかりますので、気にしないでください:)

edit2: JSP コード内の JSP タグ間の改行が出力ストリームになってしまうのではないですか? サーバーから返された応答が失われる可能性はありますか? PDF の形式については何も知りませんが、ファイル内の特定の場所にある特定の「マーカー」文字に依存しますか? (返されたエラー メッセージは、そのように聞こえます)。

于 2008-10-20T15:59:19.650 に答える
0

私はマット bに同意します。おそらく、JSP タグ間のスペースです。ディレクティブを入れてみる

<%@ page trimDirectiveWhitespaces="true" %>
于 2008-10-20T16:42:22.260 に答える