miércoles, 13 de junio de 2012


How to export to excel datatable with header / column group


Voy a intentar explicar como he resuelto el asunto de exportar una tabla con cabeceras agrupadas como las que tiene ICEfaces <ice:dataExport> o PrimeFaces, ya que su componente de exportación directamente no sirve para este tipo de cabeceras.

En principio yo divido el trabajo en dos partes, por una parte defino la cabecera agrupada en un fichero xml y a continuación le añado las filas de la tabla con los datos en si.

Tabla:

1.- Cabecera definida en un xml
2.-Lista con los datos de la tabla.


Mi fichero xml para la definición de la cabecera tendría un aspecto similar a este:

<?xml version="1.0" encoding="UTF-8"?>


<header>
< cabecera tipo="1">
< table id="1101" cols="8">
< tr>
< td align="center" styleClass="logo" width="20%"
firstCol="0" rowspan="3" colspan="3" titulo="logo"
media="/xmlhttp/images/logobd3.gif" heigth="77px" />
< td align="center" styleClass="LCAB" colspan="5"
firstCol="3" titulo="header.id_1101.Titulo" />
< /tr>
< tr>
< td align="center" colspan="2" styleClass="LN"
firstCol="3" titulo="header.id_1101.row_1" />
< td align="center" colspan="2" styleClass="LN"
firstCol="5" titulo="header.id_1101.row_2" />
< td align="center" rowspan="2" styleClass="LN"
firstCol="7" titulo="header.id_1101.row_3" />

< /tr>
< tr>

< td titulo="header.id_1101.col_1" />

< td titulo="header.id_1101.col_2" />

< td titulo="header.id_1101.col_3" />

< td titulo="header.id_1101.col_4" />
< /tr>
< /table>
< /cabecera>



ok, ahora que tenemos la definición de la cabecera tipo html de siempre, lo que hay que hacer es procesar el fichero. Yo utilizo DOM para procesarlo y JXL para generar el fichero excel, aprovecho así el componente outputresource de ICEfaces.

Me he creado un clase para hacer todo el trabajo, desde leer el fichero hasta generar el fichero  excel.

Hay parámetros que yo utilizo pero que a efectos de ejemplo, pueden sobrar.


public class ExcelExport {
private String mostrarBotonExcel;

private List < ArrayList < String > > tdatos = new ArrayList < ArrayList < String > > ();

private Nodo nodo;

private ResourceBean resourceBean;
// Contiene la hoja excel a mostrar. Es global
WritableWorkbook wb = null;

WritableSheet excelSheet = null;

Document document;



public ExcelExport() {
super();
creaRecurso();
}


public void creaRecurso(List> tdatos, Nodo nodo) {
this.tdatos = tdatos;
this.nodo = nodo;
parametros = true;

creaExcel();

try {
resourceBean = downloadFile("pdfFileName", wb);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}




private void creaExcel() {

if (parametros) {

HttpSession session = (HttpSession) FacesContext
.getCurrentInstance().getExternalContext().getSession(true);

String basePath = "/excel";
String archivo = "fichero.xls";
String archivoCreado = session.getServletContext().getRealPath(
basePath + "/" + archivo);
String inputFile = archivoCreado;
File file = new File(inputFile);
WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setLocale(new Locale("es", "ES"));

try {
wb = Workbook.createWorkbook(file, wbSettings);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Creo la hoja del libro
wb.createSheet("excel", 0);
excelSheet = wb.getSheet(0);

try {

parseTest();

addData2Excel();

fila += filaExcel;
addInfo2Excel();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

try {
wb.write();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
wb.close();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mostrarBotonExcel = "display: block";
} else {
System.out.println(tdatos.size());

HttpSession session = (HttpSession) FacesContext
.getCurrentInstance().getExternalContext().getSession(true);

String basePath = "/excel";
String archivo = "fichero.xls";
String archivoCreado = session.getServletContext().getRealPath(
basePath + "/" + archivo);
String inputFile = archivoCreado;
File file = new File(inputFile);
WorkbookSettings wbSettings = new WorkbookSettings();
wbSettings.setLocale(new Locale("es", "ES"));

try {
wb = Workbook.createWorkbook(file, wbSettings);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Creo la hoja del libro
wb.createSheet("tabla_principal", 0);
excelSheet = wb.getSheet(0);

Date t0 = new java.util.Date();
try {
excelSheet.addCell(new Label(0, 0, "" + t0.getTime()));
} catch (RowsExceededException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

try {
wb.write();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
wb.close();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

public ResourceBean downloadFile(String fileName, WritableWorkbook wb)
throws IOException, IllegalArgumentException {

// System.out.println("downloadFile1()");

Resource res = null;

ServletContext context = ((HttpSession) FacesContext
.getCurrentInstance().getExternalContext().getSession(false))
.getServletContext();
try {

// Aqui esta el asunto
res = new ByteArrayResource(toByteArray(new FileInputStream(
new File(context.getRealPath("/excel") + "/fichero.xls"))));
} catch (Exception e) {
System.out.println("error: " + e.getMessage());
}

return new ResourceBean(res, "fichero.xls", "fileDescription");

}

public static byte[] toByteArray(InputStream input) throws IOException {

ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len = 0;

while ((len = input.read(buf)) > -1)
output.write(buf, 0, len);
return output.toByteArray();
}



}



El tema del outputResource de ICEfaces es que DEBE existir el recurso para que se pinte el botón en la página, por eso lo de los parámetros, la primera vez genero un fichero excel de test y sobre ese escribo lo que obtenga.

En el código anterior también está como leer el fichero de la aplicación. Yo utilizo un servidor Tomcat 5.0.16.


Bueno, y ahora veamos un poco la función parseTest que se encarga de leer el fichero xml y generar un objeto DOM, que luego recorro como un árbol.


private void parseTest() {


fila = 0;

HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(true);
String basePath = session.getServletContext().getRealPath(
"/WEB-INF/resources");


 String fichero = "/" + "headerTest.xml";
basePath += fichero;


try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();

document = builder.parse(new File(basePath));
document.getDocumentElement().normalize();
} catch (SAXParseException spe) {
// Error generated by the parser
System.out.println("\n** Parsing error" + ", line "
+ spe.getLineNumber() + ", uri " + spe.getSystemId());
System.out.println(" " + spe.getMessage());
// Use the contained exception, if any
Exception x = spe;
if (spe.getException() != null)
x = spe.getException();
x.printStackTrace();
} catch (SAXException sxe) {
// Error generated by this application
// (or a parser-initialization error)
Exception x = sxe;
if (sxe.getException() != null)
x = sxe.getException();
x.printStackTrace();
} catch (ParserConfigurationException pce) {
// Parser with specified options can't be built
pce.printStackTrace();
} catch (IOException ioe) {
// I/O error
ioe.printStackTrace();
}

Application application = FacesContext.getCurrentInstance()
.getApplication();

// Here begins
Element rootElement = document.getDocumentElement();
if (rootElement != null) {
// System.out.println("rootElement != null");
} else {
System.out.println("rootElement == null");
}



// buildTree realiza todo el trabajo.



buildHeader(rootElement, nodo.getId(), id_header, "1");


}

ok, en rootElement tenemos ya la dichosa cabecera que llevo esperando 3 años para que la implementen los señores de ICEfaces y no ha habido manera.



private void buildHeader(Element rootElement, String id, String id_header,
String nTabla) {

addChildren((Node) rootElement, id, id_header, nTabla);
}

Y addChildren (los parámetros son los que yo utilizo, cada uno pues como más le guste).


private void addChildren(Node parentXMLElement, String id,
String id_header, String nTabla) {

System.out.println("addChildren");
HeaderRow headerRow;
UIColumn column;
HtmlOutputText someText;

boolean encontradoTipo = false;

NodeList childElements = parentXMLElement.getChildNodes();

for (int i = 0; i < childElements.getLength(); i++) {
Node childElement = childElements.item(i);

if (!(childElement instanceof Text || childElement instanceof Comment)) {
boolean tieneHijos = false;

if (childElement.hasChildNodes()) {
if (childElement.getNodeName().equalsIgnoreCase("cabecera")) {
// Preguntar por el tipo de cabecera y dependiendo de
// esta
// hacer una procesamiento diferente de las tablas
encontradoTipo = true;
tipoCabecera = buscaAtributo(childElement, "tipo");
}
if (childElement.getNodeName().equalsIgnoreCase("table")) {
switch (Integer.parseInt(tipoCabecera)) {
case 1:
// System.out.println("tipoCabecera: " + 1);
if (buscaAtributo(childElement, "id", id)) {

procesarTabla(childElement);

// Extraigo los parametros de la tabla que
// necesito
nColumnas = Integer.parseInt(buscaAtributo(
childElement, "cols"));

}
break;


}

}

} else {
if (childElement.getNodeName().equalsIgnoreCase("tr")) {

}
}
addChildren(childElement, id, id_header, nTabla);
}

}

}




A continuación dos funciones para buscar atributos y valores de los atributos en un nodo.

private boolean buscaAtributo(Node childElement, String Atributo,
String valorAtributo) {

boolean encontrado = false;
NamedNodeMap elementAttributes = childElement.getAttributes();
if (elementAttributes != null && elementAttributes.getLength() > 0) {
for (int i = 0; i < elementAttributes.getLength(); i++) {
Node attribute = elementAttributes.item(i);
if (attribute.getNodeName().equalsIgnoreCase(Atributo)) {
if (attribute.getNodeValue()
.equalsIgnoreCase(valorAtributo)) {

encontrado = true;
}
}
}
}
return (encontrado);
}

private String buscaAtributo(Node childElement, String Atributo) {
boolean encontrado = false;
String valorAtributo = "";
NamedNodeMap elementAttributes = childElement.getAttributes();
String nombreAtributo = "";
String treeNodeLabel = childElement.getNodeName();
if (elementAttributes != null && elementAttributes.getLength() > 0) {
for (int i = 0; i < elementAttributes.getLength(); i++) {
Node attribute = elementAttributes.item(i);
if (attribute.getNodeName().equalsIgnoreCase(Atributo)) {
valorAtributo = attribute.getNodeValue();
encontrado = true;

}
}
}
return (valorAtributo);
}




Y finalmente el asunto del excel. Yo utilizo las regiones de jxl para crear celdas combinadas como en una cabecera agrupada y funciona bastante bien. De esta manera puedo general cualquier cabecera combinada por muy grande y complicada que sea, siempre, de forma automática.


private void procesarTabla(Node parentXMLElement) {

boolean image = false;
int firstRowR = 0, lastRowR = 0, firstColR = 0, lastColR = 0;
int iFirstCol = 0;
String SCColor = "";

NodeList childElements = parentXMLElement.getChildNodes();
for (int i = 0; i < childElements.getLength(); i++) {
Node childElement = childElements.item(i);
if (childElement.getNodeName().equalsIgnoreCase("tr")) {

firstRowR = fila;
fila++;

NodeList childElements2 = childElement.getChildNodes();
// Procesamos las columnas
for (int j = 0; j < childElements2.getLength(); j++) {
Node childElement2 = childElements2.item(j);
if (childElement2.getNodeName().equalsIgnoreCase("td")) {

// Obtenemos los atributos
// El primero es la columna de inicio
String firstCol = buscaAtributo(childElement2,
"firstCol");
if (!firstCol.equals("")) {

firstColR = Integer.parseInt(firstCol);
iFirstCol = Integer.parseInt(firstCol);

}

String rowspan = buscaAtributo(childElement2, "rowspan");
if (!rowspan.equals("")) {
lastRowR = firstRowR + Integer.parseInt(rowspan)
- 1;
} else {
lastRowR = firstRowR;
}

String colspan = buscaAtributo(childElement2, "colspan");
if (!colspan.equals("")) {

lastColR = iFirstCol + Integer.parseInt(colspan)
- 1;


} else {
lastColR = iFirstCol;
}
String align = buscaAtributo(childElement2, "align");
if (!(align.equals(""))) {

}
String styleClass = buscaAtributo(childElement2,
"styleClass");
if (!styleClass.equals("")) {
SCColor = getColor(styleClass);
} else {
SCColor = "";
}
String titulo = buscaAtributo(childElement2, "titulo");
if (!(titulo.equals(""))) {

}


try {
WritableFont cabeceraFont = new WritableFont(
WritableFont.ARIAL, 10, WritableFont.BOLD,
true);

WritableCellFormat fCabecera = new WritableCellFormat(
cabeceraFont);
fCabecera.setAlignment(Alignment.CENTRE);
fCabecera
.setVerticalAlignment(VerticalAlignment.CENTRE);

if (!(SCColor.equalsIgnoreCase(""))) {

fCabecera.setBackground(Colour.AQUA);
}

fCabecera.setBorder(Border.ALL,
BorderLineStyle.THIN);

if (titulo.equalsIgnoreCase("logo")) {
String media = buscaAtributo(childElement2,
"media");

HttpSession session = (HttpSession) FacesContext
.getCurrentInstance()
.getExternalContext().getSession(true);

String archivoCreado = session
.getServletContext().getRealPath(
"/" + media);

String inputFile = archivoCreado;
// Meter una imagen
WritableImage wi = new WritableImage(firstColR,
firstRowR, lastColR - firstColR + 1,
lastRowR - firstRowR + 1, new File(
archivoCreado));
excelSheet.mergeCells(firstColR, firstRowR,
lastColR, lastRowR);
excelSheet.addImage(wi);
image = true;
}

if (image == false) {

excelSheet.mergeCells(firstColR, firstRowR,
lastColR, lastRowR);
Label miTexto = new Label(firstColR, firstRowR,
MessageBundleLoader.getMessage(titulo),
fCabecera);
excelSheet.addCell(miTexto);
}
image = false;

} catch (RowsExceededException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

}
}

}


Botón para generar el fichero

<ice:commandButton id="BLImgExcel"
rendered="#{ miBean .mostrarBotonExcel}"
styleClass="boton-submit"
image="/xmlhttp/#{localeBean.images}/submit-naranja.gif"
actionListener="#{miBean.beforeSubmitExcel}"
action="#{metodos.submitExcel}" />


Falta el componente que pinta el fichero.

<div id="idExcel" style="#{excelExport.mostrarBotonExcel}"><ice:outputResource
label="#{msgs['generar.fichero.excel']}"
resource="#{excelExport.resourceBean.resource}"
mimeType="application/vnd.ms-excel"
image="./xmlhttp/images/excel_icon.png"
fileName="#{excelExport.resourceBean.fileName}" attachment="true"
shared="false" /></div>

y esto es todo, aseguro que funciona.

La putada del asunto es que tengo que meter en las definiciones de las cabeceras el parámetro firstCol para indicar donde comienza la celda, pero por lo demás va como la seda. Tengo alrededor de 500 cabeceras diferentes definidas en varios ficheros xml y en principio, genial.

Espero que le sirva a alguien.

Salu2








jueves, 28 de mayo de 2009

ICEfaces 1.8.0 + <ice:outputResource/> (english version)

Hi

I’m going to try to explain how to show a list of file from a folder so you can download using the new <ice:outputResource/> of ICEfaces 1.8.0

In the component-showcase example you can download just one file, and I wanted to show a list of files from a folder and download it all. After thinking on it a lot and with the help of lmaciass from the ICEfaces forum I devoloped a working example, and I’m going to try to explain.

Step 1:

Create a class with the information of the file and the resoruce to create, Resource (import com.icesoft.faces.context.Resource;):

public class ResourceBean {

Resource resource;
String fileName;
String fileDescription;
/**
* @param resource
* @param fileName
* @param fileDescription
*/
public ResourceBean(Resource resource, String fileName,
String fileDescription) {

this.resource = resource;
this.fileName = fileName;
this.fileDescription = fileDescription;
}
Añadir los getters/setters que faltan y listo
........
}


Step 2:

Create a class to read from the folder and create a list (to show in datatable) of ResourceBean objects. Each of this object will contain the information to download.


public class RecursoDescarga {

// Lista con cada uno de los recursos
private List resourceBeanList = null;
// Recurso independiente para añadir a la lista de recursos
private ResourceBean resourceBean = null;


public RecursoDescarga() {
init();
}

private void init() {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(true);
//UPLOAD_PATH2 es algo así como "upload/";
//Cada uno tendrá que modificarlo donde lo tengo, en mi caso justo bajo el WebContent
String basePathFile = session.getServletContext().getRealPath(
Rutas.UPLOAD_PATH2);

File dir = new File(basePathFile);
List list = getFileListing(dir);

ArrayList items = new ArrayList();
for (int i = 0; i < list.size(); i++) {
String pdfFileName = ((File) list.get(i)).getName();
try {

resourceBean = downloadFile(basePathFile, pdfFileName, "");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
items.add(resourceBean);
}
resourceBeanList = items;

Step 3:

The downloadFile method:

public ResourceBean downloadFile(String path, String fileName,
String fileDescription) throws IOException,
IllegalArgumentException {

if (path == null || path.equals("") || fileName == null
|| fileName.equals("")) {
throw new IllegalArgumentException("Argumento Ilegal");
}
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();

Resource res = new ByteArrayResource(toByteArray(ec
.getResourceAsStream(Rutas.UPLOAD_PATH4 + "/" + fileName)));

return new ResourceBean(res, fileName, fileDescription);

}

public static byte[] toByteArray(InputStream input) throws IOException {

ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len = 0;
while ((len = input.read(buf)) > -1)
output.write(buf, 0, len);
return output.toByteArray();
}

Step 4:

Finally the two method to read the files from the folder:

public List getFileListing(File dir) {
List list = getFileListingNoSort(dir);
Collections.sort(list);

return list;

}

private List getFileListingNoSort(File dir) {
List list = new ArrayList();
File[] filesAndDirs = dir.listFiles();
List filesDirs = Arrays.asList(filesAndDirs);

for (File file : filesDirs) {
if (file.isFile()) {
list.add(file);
}
}

return list;
}


Step 5:

jspx page

<dataTable id="downloadFiles"
value="#{recursoDescarga.resourceBeanList}" var="resources">
<ice:column>
<f::facet name="header">
<ice:outputText style="text-align:left;"
value="#{msgs['nombre.de.archivo']}" />
</f::facet>
<ice:outputText value="#{resources.fileName}" />
</ice:column>
<ice:column style="text-align:center;">
<f::facet name="header">
<ice:outputText value="#{msgs['descargar']}" />
</f::facet>

<ice:outputResource label="#{msgs['descargar']}"
resource="#{resources.resource}"
image="./xmlhttp/images/LogoPDF.gif" mimeType="application/pdf"
fileName="#{resources.fileName}" attachment="true"
shared="false" style="width:150px" />
</ice:column>

<ice:column>
< f::facet name="header">
<ice:outputText value="#{msgs['descripcion']}" />
</f::facet>
<ice:outputText value="#{resources.fileDescription }" />
</ice:column>
</ice:dataTable>


Step 6:

Declare RecursoDescarga in faces-config-bean.xml


I hope it Works

Thanks

miércoles, 27 de mayo de 2009

ICEfaces 1.8.0 + <ice:outputResource/>

Hola.

Voy a intentar explicar como mostrar una lista de ficheros para descargar utilizando el nuevo <ice:outputResource/> de ICEfaces 1.8.0

En el ejemplo que aparece en el component-showcase sólo permite descargar un fichero y yo lo que quería era poder mostrar una lista de ficheros ubicados en un directorio particular con la opción de descargar cualquiera de ellos. Después de devanarme los sesos y con la ayuda de lmaciass en el foro de icefaces he conseguido que funcione y voy a intentar explicar como.

Paso 1:

Crear una clase que contenga la información de cada uno de los ficheros, así como el elemento Resource (import com.icesoft.faces.context.Resource;) tal que así:

public class ResourceBean {

Resource resource;
String fileName;
String fileDescription;
/**
* @param resource
* @param fileName
* @param fileDescription
*/
public ResourceBean(Resource resource, String fileName,
String fileDescription) {

this.resource = resource;
this.fileName = fileName;
this.fileDescription = fileDescription;
}
Añadir los getters/setters que faltan y listo
........
}


Paso 2:

Crear una clase que se encarge de leer desde la carpeta donde tengo los ficheros y crear una lista (para mostrar con el datatable) de objetos tipo ResourceBean. Cada uno de ellos contendrá la información para cada fichero a descargar.

public class RecursoDescarga {

// Lista con cada uno de los recursos
private List resourceBeanList = null;
// Recurso independiente para añadir a la lista de recursos
private ResourceBean resourceBean = null;


public RecursoDescarga() {
init();
}

private void init() {
HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
.getExternalContext().getSession(true);
//UPLOAD_PATH2 es algo así como "upload/";
//Cada uno tendrá que modificarlo donde lo tengo, en mi caso justo bajo el WebContent
String basePathFile = session.getServletContext().getRealPath(
Rutas.UPLOAD_PATH2);

File dir = new File(basePathFile);
List list = getFileListing(dir);

// ArrayList items = new ArrayList();
ArrayList items = new ArrayList();
for (int i = 0; i < list.size(); i++) {
String pdfFileName = ((File) list.get(i)).getName();
try {

resourceBean = downloadFile(basePathFile, pdfFileName, "");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
items.add(resourceBean);
}
resourceBeanList = items;

Paso 3:

A continuación el método downloadFile:

public ResourceBean downloadFile(String path, String fileName,
String fileDescription) throws IOException,
IllegalArgumentException {

if (path == null || path.equals("") || fileName == null
|| fileName.equals("")) {
throw new IllegalArgumentException("Argumento Ilegal");
}
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();

Resource res = new ByteArrayResource(toByteArray(ec
.getResourceAsStream(Rutas.UPLOAD_PATH4 + "/" + fileName)));

return new ResourceBean(res, fileName, fileDescription);

}

public static byte[] toByteArray(InputStream input) throws IOException {

ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buf = new byte[4096];
int len = 0;
while ((len = input.read(buf)) > -1)
output.write(buf, 0, len);
return output.toByteArray();
}

Paso 4:

Por último os pongo las dos rutinas para obtener los ficheros, que las he encontrado por ahí, y las he utilizado tal cual.


public List getFileListing(File dir) {
List list = getFileListingNoSort(dir);
Collections.sort(list);

return list;

}

private List getFileListingNoSort(File dir) {
List list = new ArrayList();
File[] filesAndDirs = dir.listFiles();
List filesDirs = Arrays.asList(filesAndDirs);

for (File file : filesDirs) {
if (file.isFile()) {
list.add(file);
}
}

return list;
}


Paso 5:

Crear la página .jspx

<dataTable id="downloadFiles"
value="#{recursoDescarga.resourceBeanList}" var="resources">
<ice:column>
<f:facet name="header">
<ice:outputText style="text-align:left;"
value="#{msgs['nombre.de.archivo']}" />
</f:facet>
<ice:outputText value="#{resources.fileName}" />
</ice:column>
<ice:column style="text-align:center;">
<f:facet name="header">
<ice:outputText value="#{msgs['descargar']}" />
</f:facet>

<ice:outputResource label="#{msgs['descargar']}"
resource="#{resources.resource}"
image="./xmlhttp/images/LogoPDF.gif" mimeType="application/pdf"
fileName="#{resources.fileName}" attachment="true"
shared="false" style="width:150px" />
</ice:column>

<ice:column>
< f:facet name="header">
<ice:outputText value="#{msgs['descripcion']}" />
</f:facet>
<ice:outputText value="#{resources.fileDescription }" />
</ice:column>
</ice:dataTable>


Paso 6:

Declarar el objeto en el faces-config-bean.xml


Bueno, espero haber podido aportar mi granito de arena a este asunto.

Perdonad que no he ajustado los textos correctamente.

Cualquier duda, corrección o comentario

Salu2