Frage

Verwenden Sie JDK 1.6, JSF 2.1, Primefaces 2.2.1, POI 3.2 und Apache Tomcat 7

Ich versuche, ein Servlet einzurichten, um einen Download einer Excel -Datei basierend auf der Benutzerauswahl zu ermöglichen. Das Excel -Dokument wird zur Laufzeit erstellt.

Keine Fehler und der Code kommt in das Servlet.

Ich klicke auf die Schaltfläche und nichts passiert. Ich verwende nicht den Datentatable -Export, den Primefaces verwendet, da ich die Daten im Excel -Dokument neu ordnen und benutzerdefinierte Formatierung durchführen müssen.

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();
}

Projectportbean.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>
War es hilfreich?

Lösung

Es gibt zwei Probleme.

Das erste Problem ist, dass die <p:commandButton> Sendet standardmäßig eine AJAX -Anfrage. Diese Anfrage wird vom JavaScript -Code entlassen. JavaScript kann jedoch nichts mit einer Antwort tun, die einen Datei -Download enthält. Aufgrund von Sicherheitsbeschränkungen kann JavaScript a nicht erzeugen a Speichern als Dialog oder so. Die Antwort wird im Grunde genommen vollständig ignoriert.

Sie müssen hinzufügen ajax="false" zu <p:commandButton> So schalten Sie AJAX aus, damit die Taste eine normale synchrone HTTP -Anforderung abfeuert oder Sie sie durch Standard ersetzen müssen <h:commandButton>.

<p:commandButton ajax="false" ... />

oder

<h:commandButton ... />

Das zweite Problem ist, dass Ihr Servlet die Excel -Datei überhaupt nicht in die Antwort schreibt, sondern in eine lokale Datei, die im Arbeitsverzeichnis des Servers gespeichert ist. Grundsätzlich enthält die HTTP -Antwort nichts. Sie müssen passieren HttpServletResponse#getOutputStream() zum WorkBook#write() Methode.

workbook.write(response.getOutputStream());

Ich frage mich, wie das Servlet hier nützlich ist. Möchten Sie es außerhalb von JSF wiederverwenden? Wenn nicht, müssen Sie überhaupt nicht unbedingt in das Servlet versenden, sondern nur den gleichen Code in der Aktionsmethode von Bean ausführen. Das leer catch Block ist auch nicht schön. Ich würde es einfach als deklarieren throws in der Methode oder zumindest überdenken als new FacesException(e).


Aktualisieren Nach den Kommentaren scheinen Sie überhaupt nicht an dem Servlet interessiert zu sein. Hier ist ein kleines Umschreiben, wie Sie die Excel -Datei programmgesteuert in einer JSF -Aktionsmethode senden können.

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();
}

Andere Tipps

Hier ist das, was ich zuvor geschrieben habe und der Fall;

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 -Seite (mit 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);
    }

}

Ich würde auch empfehlen, die PrimeFaces -Felldown -Ladung zu verwenden. Abhängig von Ihrer Struktur könnte dies alles viel einfacher machen. Sie müssten kein Servlet nur eine verwaltete Bohne erstellen, die eine liefern kann ContentStream.

Da Sie bereits den Servlet geschrieben haben, macht es keinen Sinn, sich zu ändern, nur zu Gedanken.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top