Question

Utilisation de JDK 1.6, JSF 2.1, 2.2.1 PrimeFaces, POI 3.2 et Apache Tomcat 7

Je suis en train d'installer un servlet pour permettre le téléchargement d'un fichier Excel en fonction de la sélection de l'utilisateur. Le document Excel est créé lors de l'exécution.

erreurs non et le code ne se dans le servlet.

je clique sur le bouton et rien ne se passe. Je n'utilise pas l'exportation datatable que PrimeFaces utilisations parce que je dois faire et réordonnancement un formatage personnalisé sur les données contenues dans le document 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>
Était-ce utile?

La solution

Il y a deux problèmes.

Le premier problème est que le <p:commandButton> envoie par défaut une requête Ajax. Cette demande est tirée par le code JavaScript. Cependant, JavaScript ne peut rien faire avec une réponse qui contient un téléchargement de fichier. En raison des restrictions de sécurité JavaScript ne peut pas engendrer une Enregistrer sous dialogue ou quelque chose. La réponse est essentiellement totalement ignorée.

Vous devez ajouter ajax="false" à <p:commandButton> tourner ajax de sorte que le bouton déclenche une requête HTTP synchrone normale, ou si vous devez le remplacer par <h:commandButton> standard.

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

ou

<h:commandButton ... />

Le deuxième problème est que votre servlet ne pas écrire le fichier Excel à la réponse du tout, mais plutôt à un fichier local qui est stocké dans le répertoire de travail du serveur. En gros, la réponse HTTP ne contient rien . Vous devez passer HttpServletResponse#getOutputStream() à la méthode WorkBook#write().

workbook.write(response.getOutputStream());

Sur une note sans rapport, je me demande comment le servlet est utile ici. Est-ce que vous voulez réutiliser l'extérieur JSF? Sinon, vous ne devez pas nécessairement l'envoi au servlet du tout, mais il suffit d'exécuter le même code dans la méthode d'action de haricot. Ce vide bloc catch est pas agréable. Je venais de le déclarer comme throws dans la méthode ou au moins rethrow comme new FacesException(e).


Mise à jour selon les commentaires que vous semble pas être intéressé par le servlet du tout. Voici une ré-écriture mineur comment vous pouvez envoyer le fichier Excel par programme dans une méthode d'action JSF.

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

Autres conseils

Voici que je l'ai écrit avant et travailler le cas;

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 côté (avec 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);
    }

}

Je vous recommande également regarder en utilisant le PrimeFaces FileDownload. En fonction de votre structure, il pourrait faire tout cela beaucoup plus facile. Vous auriez pas à créer un servlet juste un bean géré qui peut fournir un ContentStream.

Puisque vous avez déjà le servlet écrit cependant, il n'y a pas de point de changement, juste la nourriture pour la pensée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top