2017-06-23 15 views
0

JasperReportを使用してレポートをPDFにエクスポートしています。コードは正常に実行され、例外メッセージはコンソール/ログに表示されません。ただし、レポートはブラウザにエクスポートされません。言い換えれば、レポートが作成されていて、私はそれをダウンロードしたりアクセスしたりすることができません。ここでOutputStreamがPDFにエクスポートされていないJasperReport

は輸出コードです:

public void generatePDFReport(Map<String, Object> parameters, JRDataSource jrDataSource, String resource, String filename) 
{ 
    OutputStream os = null; 
    try{ 
     FacesContext context = FacesContext.getCurrentInstance(); 
     HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); 
     os = response.getOutputStream(); 

     InputStream reportTemplate = this.getClass().getClassLoader().getResourceAsStream(resource); 
     byte[] pdf = null; 

     try { 
      JasperDesign masterDesign = JRXmlLoader.load(reportTemplate); 
      masterReport = JasperCompileManager.compileReport(masterDesign); 
      masterReport.setWhenNoDataType(WhenNoDataTypeEnum.ALL_SECTIONS_NO_DETAIL); 
      JasperPrint masterPrint = JasperFillManager.fillReport(masterReport, parameters, jrDataSource); 
      pdf = JasperExportManager.exportReportToPdf(masterPrint); 
     } catch (JRException e) { 
      log.error(e); 
     } 
     response.setContentType("application/pdf"); 
     response.setContentLength(pdf.length); 
     response.setHeader("Content-disposition", "attachment; filename=\""+filename+"\""); 

     context.responseComplete(); 

     os.write(pdf); 

     pdf = null; 
    }catch(Exception e){ 
     log.error(e); 
    }finally{ 
     try{ 
      os.flush(); 
      os.close(); 
     }catch(IOException e){ 
      log.error(e); 
     } 
    } 
} 

私はそれが別のレポートのために正常に動作ようなコードは何も問題がないことをほぼ100%確信しています(私はいくつかの他のレポートに同じ輸出コードを実行し、これを除いてすべて期待どおりに動作します)。

これを知って、私はそれがレポート自体と関係があると考えました。このレポートはjrxml JasperReportファイルです。レポートはiReportを使用して作成されました。しかし、私は上記のコードをダウンロードフォルダに保存するだけで、レポートは完全にうまく作成されています。

問題は、レポートがバックエンドで正常に作成されていても、期待通りにフロントエンド(ブラウザ)に送信されていないことです。

このレポートが機能しない理由については、私は何の示唆もありません。

+0

私はpdf = nullが好きではありません。ストリーミングするときに書き込みを行い、最後に移動し、さらにいくつかのログを追加してbyte.size eccを取得します.Jasperレポートタグの属性として設定できるWhenNoDataType、 Javaで設定する必要はありません。 –

+0

@PetterFriberg pdf = nullをコメントアウトすると、目に見える効果はありません。まだ動作していません。 byte.sizeに関しては、このレポートのために約7900バイトです。私はレポートが作成され、正常に移入されたと信じています。何か案は? – AntonioK

+0

@DaveJarvis '.jasper'ファイルを直接実行することは役に立ちませんでした。私は同じ問題を抱えています。他のアイデア? – AntonioK

答えて

0

私は私の問題を解決しました。最終的に、レポート生成コードまたはレポートに何も問題はないことがわかりましたが、出力ストリームがレポートをブラウザにエクスポートすることを妨げるajaxの問題がありました。

0

ので、豆の内部でコードを実行すると、問題がある:getOutputStream

  • 唯一のコールがHTTPリクエスト
  • のWebフレームワーク(J2EE/JSF)ごとに許可される可能性が高いすでに
  • HTTPヘッダを書いていますJSFページは既に一時バッファー内にHTMLとして書き込まれている可能性があります(responseComplete()を呼び出すとフラッシュされた可能性があります)。
  • ヘッダがリセットされることができ、それはresponseComplete()を呼び出すと、ブラウザ

サーブレットを使用するようにPDFコンテンツと一緒に任意のHTMLをフラッシュgetOutputStream問題

  • に役立つことはありません。

    protected void disableCache() { 
        // https://tools.ietf.org/html/rfc7234#section-7.1.3 
        setHeader(CACHE_CONTROL, "private, no-store, no-cache, must-revalidate"); 
    
        // https://tools.ietf.org/html/rfc7234#section-5.3 
        setHeader(EXPIRES, "Thu, 01 Dec 1994 16:00:00 GMT"); 
    
        // https://tools.ietf.org/html/rfc7234#section-5.4 
        setHeader(PRAGMA, "no-cache"); 
    
        // https://tools.ietf.org/html/rfc7232#section-2.2 
        setHeader(LAST_MODIFIED, getServerTimestamp()); 
    } 
    
    private String getServerTimestamp() { 
        final SimpleDateFormat rfc1123 = new SimpleDateFormat(DATE_RFC_1123, getDefault()); 
    
        rfc1123.setTimeZone(getTimeZone("GMT")); 
    
        final Calendar calendar = Calendar.getInstance(); 
        return rfc1123.format(calendar.getTime()); 
    } 
    

    これは、例えば、意味:

    をサーブレットのsendメソッドは、より任意のより複雑な必要はありません:古いレポートが不可能なように

    protected void send(final byte[] content) throws IOException { 
        setContentLength(content.length); 
    
        try (final OutputStream out = getOutputStream()) { 
         out.write(content); 
        } 
    } 
    

    また、キャッシュを設定することを検討します

    @WebServlet(
         name = "ReportServlet", 
         urlPatterns = {PATH_SERVLET + "ReportServlet"} 
    ) 
    public class ReportServlet extends AbstractServlet { 
    } 
    

    そして、通常のアンカーリンクを使用します。

    <h:outputLink value="/app/path/servlet/Reportservlet">Run Report</h:outputLink> 
    

    要約すると、リクエストをJSFページに傍受してバイナリ・レポート・データを送信しないでください。代わりにサーブレットを使用してください。サーブレットとJSFページ間

    通信を介して行うことができる。

    • セッション変数(たHTTPSessionサーブレット側)
    • URLパラメータ

    サーブレットJSFオーバーヘッドがあるという利点を有します完全に回避されるため、レポートはユーザーの視点からより速く実行されます。また、レポートをコンパイルしないでください。.jasperファイルを直接使用してください。パフォーマンスも向上します。 (私は.jrxmlファイルを使用することを意味するわけではありませんでしたが、それは必要なステップではありません)。

  • 関連する問題