我需要在按钮点击时提供报告生成功能。我使用Liferay Portal 6.1和Tomcat 7作为Web门户,Liferay Developer Studio(Eclipse Indigo)IDE,iReport(用于创建报告模板)和JasperReports库来生成PDF。门户网站是一个票证管理系统,具有两个实体(票证和文档),这些实体通过各自的自定义portlet输入。处于编辑模式时,这两个实体都需要查看报告'功能。我已经广泛地搜索了这个问题的答案,在这里和那里拿起一个片段,但我找到的并不是我的情况。点击“查看报告”后,按钮,用户需要呈现格式化的PDF,然后用户可以决定“保存”,“打印”或“关闭”。从。我还需要将数据传递给报告,以便可以检索打开的实体(即documentId,ticketId,docType等)的信息,但是这篇文章可以在以后添加;一旦我得到一个PDF打开。
不知道如何实现这一点,我决定使用jQuery Modal来打开' viewReport.jsp'页面并处理报告。但是,此方法会产生JRException IllegalState:无法获取OutputStream,因为writer已在使用中。我在我的搜索中读到Liferay布局使用OutputStream,这可能是作者已经在使用的原因。这是我正在使用的代码:
edit_document.jsp (按钮和jQuery模态)
<!-- View Report Button at bottom of form -->
<aui:button type="button" id="viewReportBtn" value="View Report" />
<!-- URL declaration for PDF popup window -->
<portlet:renderURL var="viewReportURL" windowState="<%= LiferayWindowState.EXCLUSIVE.toString() %>" >
<portlet:param name="mvcPath" value="/html/document/viewReport.jsp" />
<portlet:param name="documentId" value="<%= Long.toString(documentID) %>" />
<portlet:param name="ticketId" value="<%= Long.toString(ticketID) %>: />
<portlet:param name="docType" value="<%= docType %>" /> <!-- This is already a String value -->
</portlet:renderURL>
<!-- jQuery to open popup window for PDF -->
<aui:script use="aui-dialog, aui-overlay-manager, dd-constrain" >
var reportDialogOptions = {
title : 'Dialog',
bodyContent : '',
centered : true,
group : default,
height : 800,
width : 1000,
modal : true,
};
$('#viewReportBtn').on('click', finction(event) {
var editFeelingDialog = new A.Dialog(
A.merge(reportDialogOptions, {
title : 'Document View Report'
})
).plugin(A.Plugin.IO,{uri : '<%= viewReportURL %>'}).render();
});
</aui:script>
viewReport.jsp (处理jrxml模板并打开PDF的页面)
<!-- viewReport.jsp page to render PDF -->
<%@ page contentType = "application/pdf" %>
<%@ page trimDirectiveWhitespaces = "true" %>
<%@ page import = "net.sf.jasperreports.engine.*" %>
<%@ page import = "java.io.File" %>
<%@ page import = "java.io.FileInputStream" %>
<%@ page import = "java.io.FileNotFoundException" %>
<%@ page import = "java.io.InputStream" %>
<%@ page import = "java.sql.Connection" %>
<%@ page import = "java.sql.SQLException" %>
<%
Connection conn = null;
try
{
String url = "jdbc:oracle:thin:@myDBSRV:1521:myDatabase";
String userName = "myUsername";
String password = "myPassword";
// Connecting to the Oracle database
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(url, username, password);
// Loading the Jasper Report file from local file system\
String jrxmlFile = session.getServletContext().getRealPath(request.getContextPath())+"\\report5.jrxml";
InputStream input = new FileInputStream(new File(jrxmlFile));
// Generate the report
JasperReport jasperReport = JasperCompileManager.compileReport(input);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPrint, null, conn);
// Export the report as a PDF
JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
}
catch (FileNotFoundExcecption ex)
{
System.out.println(ex.getMessage());
ex.printStakeTrace();
}
catch (JRException ex)
{
System.out.println(ex.getMessage());
ex.printStakeTrace();
}
catch (ClassNotFoundException ex)
{
System.out.println(ex.getMessage());
ex.printStakeTrace();
}
catch (SQLException ex)
{
System.out.println(ex.getMessage());
ex.printStakeTrace();
}
finally
{
if (conn != null)
{
conn.close();
}
}
%>
&#13;
我还尝试将java方法添加到我的DocumentPortlet.java类中,并在单击按钮时调用方法,但是我对ajax的熟悉程度不是很正确:
DocumentPortlet.java
public class DocumentPortlet extends MVCPortlet{
Connection conn = null;
// More methods for saving, editing, and deleting documents are here...
public void generateReport()
{
initConnection();
showReport();
}
public void initConnection()
{
String host = "jdbc:oracle:thin:@ncimsdbsrv:1521:ncimsdev";
String userName = "lportal";
String password = "NSS4207itnp";
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
try
{
conn = DriverManager.getConnection(host, userName, password);
}
catch (SQLException ex)
{
ex.printStackTrace();
}
}
public void showReport()
{
//Path to your .jrxml file
String reportName = "[path to file]";
//Get a stream to read the file
InputStream is = this.getClass().getClassLoader().getResourceAsStream(reportName);
try
{
//Fill the report with parameter, connection, and stream reader
JasperPrint jp = JasperFillManager.fillReport(is, null, session);
//Viewer for Jasper report
JRViewer jv = new JRViewer(jp);
//Insert viewer to a JFrame to make it showable
JFrame jf = new JFrame();
jf.getContentPane().add(jv);
jf.validate();
jf.setVisible(true);
jf.setSize(new Dimension(800, 600));
jf.setLocation(300, 100);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
catch (JRException ex)
{
ex.printStakeTrace();
}
finally
{
closeSession(session);
}
}
}
&#13;
如何以用户点击按钮并在屏幕上生成PDF的方式提供此功能?我需要一个清晰简洁的解决方案来解决这个问题。谢谢!
利
答案 0 :(得分:0)
如果有人有兴趣,我在Liferay论坛上找到答案。我的实施不正确。所以现在我在我的
中有这个<强> viewDocument.jsp:强>
<!-- View Report button at bottom of form -->
<aui:button id="viewReportBtn" value="View Report" />
<!-- URL declaration for PDF generation -->
<portlet:resourceURL id="generatePDF" var="generateReportURL" >
<portlet:param name="jspPage" value="/html/document/viewReport.jsp" />
<portlet:param name="docType" value="<%= docType %>" />
</portlet:resourceURL>
<!-- AJAX call to resource request handler in DocumentPortlet.java file -->
<aui:script use="aui-dialog, aui-overlay-manager, dd-constrain" >
$(document).ready(function()
{
$('#viewReportBtn').click(function(event)
{
$.ajax('<%= generateReportURL %>');
}
});
&#13;
我还在我的Portlet java文件中创建了ResourceRequestHandler,如下所示:
<强> DocumentPortlet.java:强>
public class DocumentPortlet extends MVCPortlet{
Connection conn = null;
// More methods to add, update, and delete here
@Override
public void serveResource(ResourceRequest request, ResourceResponse response)
throws IOException, PortletException
{
String url = "jdbc:oracle:thin:@myDatabaseSrv:1521:myDatabaseSid";
String user = "myUserName";
String pass = "myPassword";
String docType = ParamUtil.getString(request, "docType");
try
{
// Connect to database
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(url, user, pass);
// Load JRXml file from local file system
String jrxmlFile = "C:\\Reports\\report5.jrxml";
InputStream input = new FileInputStream(new File(jrxmlFile));
// Generate report
JasperReport jasperReport = JasperCompileManager.compileReport(input);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPrint, null, conn);
/***** Display PDF in Adobe Reader *****/
// Create new OutputStream where data is written to byte array[]
ByteArrayOutputStream output = new ByteArrayOutputStream();
// Export the report to PDF format
JasperExportManager.exportReportToPdfStream(jasperPrint, output);
// Create a String for thr report title
final String fileName = docType + ".pdf";
//Create a new stream and call the report
OutputStream pdfFile = new FileOutputStream(new File(fileName));
//Write the PDF
pdfFile.write(output.toByteArray());
//Clean the PDF
pdfFile.flush();
//Close it
pdfFile.close();
//Run the brand new PDF report
final String PDF_RUN = "rundll32 url.dll, FileProtocolHandaler " + fileName;
//Execute the command
Runtime.getRuntime().exec(PDF_RUN);
}
catch(FileNotFoundException ex)
{
System.out.println("File not found on file system, check file path!!" + ex.getMessage());
ex.printStackTrace();
}
catch(JRException ex)
{
System.out.println("Error in Jasper Report!!" + ex.getMessage());
ex.printStackTrace();
}
catch(ClassNotFoundException ex)
{
System.out.println("Oracle Class for driver not found!!" + ex.getMessage());
ex.printStackTrace();
}
catch(SQLException ex)
{
System.out.println("Error getting connection to database!!" + ex.getMessage());
ex.printStackTrace();
}
}
}
&#13;
这消除了我得到的IllegalStateException,并且会在Adobe Reader中打开pdf,但是,它会在服务器上打开它。因此,问题仍然存在。有人知道如何在客户机上打开这个pdf吗?