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

8 comentarios:

  1. hola, me peudes enviar codio de esto plz , q no me sale :(

    ResponderEliminar
  2. david si me puedes ayudar plz, mi mail es ricardoulloac@gmail.com

    ResponderEliminar
  3. ricardo, te he dejado en tu correo un proyecto .war en eclipse para tomcat 6, solo falta añadirle las librerias que te indico.

    Salu2
    David

    ResponderEliminar
  4. david, no se como agradecerte por todo el tiempo q te he hecho perder, muchas pero muchas gracias :).

    ResponderEliminar
  5. Hola!!

    Quería que supieras que me ha sido de gran ayuda este post con un problemilla que tenía al intentar generar un report y mostrarlo directamente desde el navegador. Soy novata con icefaces y, tras generar el pdf perfectamente, no era capaz de visualizarlo.

    Lo dicho, muchas gracias!!!

    Paula

    ResponderEliminar
  6. Muchas gracias!! Me sirvió mucho este post!

    Saludos!

    Nerina

    ResponderEliminar