[英]Export to Excel JSF and PrimeFaces
使用JDK 1.6,JSF 2.1,PrimeFaces 2.2.1,POI 3.2和Apache Tomcat 7
我正在嘗試設置一個servlet,允許根據用戶選擇下載excel文件。 excel文檔在運行時創建。
沒有錯誤,代碼確實進入了servlet。
我點擊按鈕,沒有任何反應。 我沒有使用PrimeFaces使用的數據表導出,因為我需要對Excel文檔中的數據進行重新排序和自定義格式化。
ExportExcelReports.java
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\"my.xls\"");
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellValue(0.0);
FileOutputStream out = new FileOutputStream("my.xls");
workbook.write(out);
out.close();
}
ProjectReportBean.java
public void getReportData() {
try {
FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext ectx = ctx.getExternalContext();
HttpServletRequest request = (HttpServletRequest) ectx.getRequest();
HttpServletResponse response = (HttpServletResponse) ectx.getResponse();
RequestDispatcher dispatcher = request.getRequestDispatcher("/ExportExcelReports");
dispatcher.forward(request, response);
ctx.responseComplete();
} catch (Exception e) {}
}
的index.xhtml
<h:form id="reportsForm">
<h:outputLabel for="report" value="Reports" /><br />
<h:selectOneMenu id="report" value="#{projectReportBean.selectedReport}" required="true" requiredMessage="Select Report">
<f:selectItem itemLabel="---" noSelectionOption="true" />
<f:selectItems value="#{projectReportBean.reports}" />
</h:selectOneMenu>
<p:commandButton action="#{projectReportBean.getReportData}" value="Export" update="revgrid" />
</h:form>
有兩個問題。
第一個問題是<p:commandButton>
默認發送一個Ajax請求。 此請求由JavaScript代碼觸發。 但是,JavaScript無法對包含文件下載的響應執行任何操作。 由於安全限制,JavaScript無法生成“ 另存為”對話框等。 響應基本上完全被忽略了。
您需要向<p:commandButton>
添加ajax="false"
以關閉ajax,以便按鈕觸發正常的同步HTTP請求,或者您需要用標准的<h:commandButton>
替換它。
<p:commandButton ajax="false" ... />
要么
<h:commandButton ... />
第二個問題是您的servlet根本不會將Excel文件寫入響應,而是寫入存儲在服務器工作目錄中的本地文件。 基本上,HTTP響應不包含任何內容 。 您需要將HttpServletResponse#getOutputStream()
傳遞給WorkBook#write()
方法。
workbook.write(response.getOutputStream());
在一個不相關的說明中,我想知道servlet在這里是如何有用的。 你想在JSF之外重用它嗎? 如果沒有,您根本不需要調度到servlet,而只需在bean的action方法中執行相同的代碼。 那空catch
塊也是不是很好。 我只是將它聲明為throws
方法或至少重新拋出它作為new FacesException(e)
。
根據你似乎對servlet不感興趣的評論進行更新 。 這是一個小改寫如何在JSF操作方法中以編程方式發送Excel文件。
public void getReportData() throws IOException {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell(0);
cell.setCellValue(0.0);
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.setResponseContentType("application/vnd.ms-excel");
externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"my.xls\"");
workbook.write(externalContext.getResponseOutputStream());
facesContext.responseComplete();
}
這是我之前寫的和工作案例;
xhtml;
<h:panelGrid id="viewCommand" style="float:right;" >
<p:commandButton value="Export Excel" icon="ui-icon-document"
ajax="false" actionListener="#{xxx.export2Excel}"
rendered="#{xxx.showTable}">
<p:fileDownload value="#{xxx.exportFile}"
contentDisposition="attachment" />
</p:commandButton></h:panelGrid>
Java端(帶POI);
protected void lOBExport2Excel(List table) throws Throwable {
Row row = null;
Cell cell = null;
try {
Workbook wb = new HSSFWorkbook();
HSSFCellStyle styleHeader = (HSSFCellStyle) wb.createCellStyle();
HSSFFont fontHeader = (HSSFFont) wb.createFont();
fontHeader.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
styleHeader.setFont(fontHeader);
Sheet sheet = wb.createSheet("sheet");
row = sheet.createRow((short) 0);
for (int i = 0; i < columnNames.size(); i++) {
cell = row.createCell(i);
cell.setCellValue(columnNames.get(i));
cell.setCellStyle(styleHeader);
}
int j = 1;
for (DBData[] temp : tabularData) {
row = sheet.createRow((short) j);
for (int k = 0; k < temp.length; k++) {
HSSFCellStyle styleRow = (HSSFCellStyle) wb.createCellStyle();
HSSFFont fontRow = (HSSFFont) wb.createFont();
fontRow.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
styleRow.setFont(fontRow);
cell = row.createCell(k);
setStyleFormat(temp[k].getDataType(), styleRow, wb);
cell.setCellValue(temp[k].toFullString());
cell.setCellStyle(styleRow);
}
j++;
}
String excelFileName = getFileName("xls");
FileOutputStream fos = new FileOutputStream(excelFileName);
wb.write(fos);
fos.flush();
fos.close();
InputStream stream = new BufferedInputStream(new FileInputStream(excelFileName));
exportFile = new DefaultStreamedContent(stream, "application/xls", excelFileName);
} catch (Exception e) {
catchError(e);
}
}
我還建議使用PrimeFaces FileDownload。 根據您的結構,它可以使這一切變得更加容易。 您不必僅創建一個可以提供ContentStream
的托管bean的servlet。
既然您已經編寫了servlet,那么就沒有必要改變,只需要深思熟慮。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.