3

生成されたPDFファイルで新しいタブを開くボタンがあります。ただし、ボタンをクリックした後、別のページに移動したいと考えています。

つまり、ボタンをクリックした後、pdf で新しいタブを開き、最初のタブの別のページに移動します。私はprimefacesを使用しp:commandButtonて試しましonclick="window.location.href='www.google.de'"たが、うまくいきません。ただしonclick="window.lalert('www.google.de')"、機能します。

これは私のコードです:

<h:form id="transForm" target="_blank">
<p:commandButton  value="Zertifikat erstellen" ajax="false" 
                                label="Speichert die Anmeldung und erstellt ein Zertifikat im PDF-Format"
                                action="#{transportErfassen.generatePDFZertifikat()}"/>

</h:form>

generatePDFZertifikat()次のコードでpdfファイルを作成しますが、ここに問題があると思います:

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();

    externalContext.setResponseContentType("application/pdf" );
    externalContext.setResponseHeader("Expires", "0");
    externalContext.setResponseHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
    externalContext.setResponseHeader("Pragma", "public");
    externalContext.setResponseHeader("Content-disposition", "inline; filename=\"" + fileName +"\"");
    externalContext.setResponseContentLength(out.length);
    externalContext.addResponseCookie(Constants.DOWNLOAD_COOKIE, "true", new HashMap<String, Object>());

    //setze explizit auf OK
    externalContext.setResponseStatus(200);     

    OutputStream os = externalContext.getResponseOutputStream();
    os.write(out, 0, out.length);
    os.flush();

    facesContext.responseComplete();       
    facesContext.renderResponse();       
4

2 に答える 2

4

基本的に、1 つの要求に対して 2 つの応答を返そうとしています。これは HTTP では機能しません。2 つの応答を送り返したい場合は、クライアントに 2 つの要求を発行させる必要があります。JavaScript をほとんど使用しないで、1 つのイベント (クリック) で複数の要求を起動することが可能です。onclickただし、フォームwindow.location送信の直前に送信ボタンをクリックすると、ボタンの元のアクションが完全に中止され、フォームが送信されます。

最善の策は、結果ページに直接移動して、window.open()ページの読み込み時に JavaScript を呼び出し、開きたい PDF ファイルの URL を指すことです。つまり、ナビゲーションを指示する PDF ファイルと一緒に HTML/JS コードを送信することはできません (PDF ファイルが明らかに破損するため)。これは、PDF をフォーム送信要求に直接返すことができないことも意味します。後続の GET 要求で PDF を取得できるように、コードを再設計する必要があります。最良の方法は、単純なサーブレットを使用することです。生成された PDF を一時的にディスク上またはセッション内に格納し、一意のキーに関連付けて、その一意のキーを要求パス情報またはパラメーターとしてwindow.open()URL のサーブレットに渡すことができます。

キックオフの例を次に示します。

初期フォーム:

<h:form>
    ...
    <p:commandButton ... action="#{bean.submit}" />
</h:form>

豆:

public String submit() {
    File file = File.createTempFile("zertifikat", ".pdf", "/path/to/pdfs");
    this.filename = file.getName();

    // Write content to it.

    return "targetview";
}

ターゲット ビュー:

<h:outputScript rendered="#{not empty bean.filename}">
    window.open('#{request.contextPath}/pdfservlet/#{bean.filename}');
</h:outputScript>

PDF サーブレット (簡潔にするために nullchecks などは省略。 Java 7 を想定Files#copy()):

@WebServlet("/pdfservlet/*")
public class PdfServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        File file = new File("/path/to/pdfs", request.getPathInfo().substring(1));
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "inline; filename=\"zertifikat.pdf\"");
        Files.copy(file.toPath(), response.getOutputStream());
    }

}
于 2013-08-20T11:20:22.627 に答える