web-dev-qa-db-ja.com

Java Webアプリケーションでブラウザにバイト[]をPDFとして送信する方法は?

アクションメソッド(JSF)では、以下のようなものがあります。

public String getFile() {
  byte[] pdfData = ...
  // how to return byte[] as file to web browser user ?
}

Byte []をPDFとしてブラウザーに送信する方法は?

18
marioosh

アクションメソッドでは、JSFフードの下から ExternalContext#getResponse() を使用してHTTPサーブレットの応答を取得できます。次に、少なくともHTTP _Content-Type_ヘッダーを_application/pdf_に設定し、HTTP _Content-Disposition_ヘッダーをattachmentに設定する必要があります(名前を付けて保存ダイアログ)またはinline(ウェブブラウザにディスプレイ自体を処理させたい場合)。最後に、IllegalStateExceptionsが飛び散らないように、後で FacesContext#responseComplete() を呼び出すことを確認する必要があります。

キックオフの例:

_public void download() throws IOException {
    // Prepare.
    byte[] pdfData = getItSomehow();
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

    // Initialize response.
    response.reset(); // Some JSF component library or some Filter might have set some headers in the buffer beforehand. We want to get rid of them, else it may collide.
    response.setContentType("application/pdf"); // Check http://www.iana.org/assignments/media-types for all types. Use if necessary ServletContext#getMimeType() for auto-detection based on filename.
    response.setHeader("Content-disposition", "attachment; filename=\"name.pdf\""); // The Save As popup magic is done here. You can give it any filename you want, this only won't work in MSIE, it will use current request URL as filename instead.

    // Write file to response.
    OutputStream output = response.getOutputStream();
    output.write(pdfData);
    output.close();

    // Inform JSF to not take the response in hands.
    facesContext.responseComplete(); // Important! Else JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}
_

とはいえ、PDFコンテンツを_byte[]_ではなくInputStreamとして取得する可能性がある場合は、代わりにそれを使用してWebアプリケーションを保存することをお勧めしますメモリーを消費します。次に、よく知られているInputStream-OutputStreamループに通常のJava IO仕方。

53
BalusC

応答でMIMEタイプを_application/x-pdf_に設定するだけです。 setContentType(String contentType) メソッドを使用して、サーブレットの場合にこれを行うことができます。
JSF/JSPでは、応答を書き込む前にこれを使用できます。

_<%@ page contentType="application/x-pdf" %>
_

およびresponse.write(yourPDFDataAsBytes());でデータを書き込みます。
しかし、この場合はサーブレットを使用することをお勧めします。 JSFは、HTMLビューのレンダリングに使用され、PDFまたはバイナリファイルではありません。

サーブレットを使用すると、これを使用できます。

_public MyPdfServlet extends HttpServlet {
    protected doGet(HttpServletRequest req, HttpServletResponse resp){
         OutputStream os = resp.getOutputStream();
         resp.setContentType("Application/x-pdf");
         os.write(yourMethodToGetPdfAsByteArray());
    } 
}
_

リソース:

5
Colin Hebert

JSFを使用してブラウザに生データを送信する場合、HttpServletResponseからFacesContextを抽出する必要があります。

HttpServletResponseを使用すると、標準のIO APIを使用してブラウザに生データを送信できます。

次にコードサンプルを示します。

public String getFile() {
    byte[] pdfData = ...

    FacesContext context = FacesContext.getCurrentInstance();
    HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
    OutputStream out = response.getOutputStream();
    // Send data to out (ie, out.write(pdfData)).
}

また、他に考慮すべきことがいくつかあります。

  • HttpServletResponseでコンテンツタイプを設定して、送信しているブラウザに通知するPDF data:response.setContentType( "application/pdf");
  • Context.responseComplete()メソッドを使用して、データをユーザーに直接送信したことをFacesContextに通知します。これにより、JSFが不要な追加処理を実行するのを防ぎます。
1
Vivien Barousse