2011-03-31 8 views
5

Necesito descargar un archivo almacenado en una base de datos. Creo que hice correctamente la consulta y la llamé, simplemente no sé cómo puedo conectar eso a un botón en una página JSF. También me pregunto, ¿tengo que guardar esa imagen en una carpeta en el servidor antes de pasarla a la página JSF. Si es así, ¿cómo puedo hacer eso?Cómo descargar un archivo almacenado en una base de datos con JSF 2.0

Esta es la consulta que utilizo para devolver el byte [] de la BD:

@NamedQuery(name = "downloadGarbage", query = "SELECT g.file FROM Garbage g WHERE g.id :idParam") 
@Entity 
public class Garbage implements Serializable { 
@Lob 
@Column(nullable = false) 
private byte[] file; 
.... 

Aquí es un EJB simple que llama a esa consulta a continuación, obtener el ID:

@Stateless(name = "ejbs/FileDownloaderEJB") 
public class FileDownloaderEJB implements IFileDownloaderEJB { 

@PersistenceContext 
private EntityManager em; 

public byte[] downloadGarbage(Long id) { 
    Query query = em.createNamedQuery("downloadGarbage"); 
    query.setParameter("idParam", id); 

    Object o = query.getSingleResult(); 
    byte[] tmpArray = (byte[]) o; 
    return tmpArray; 
} 

Ahora bien, este es la parte que me confunde, ¿cómo puedo ver eso arriba con la página JSF y el bean administrado?

@ManagedBean 
@RequestScoped 
public class DownloadController { 

@EJB 
private FileDownloaderEJB fileDownloaderEJB; 

    ... 

    private Garbage garbage; 

public void startDownload(Long id) { 
    fileDownloaderEJB.downloadGarbage(id); 
//HOW TO START THE DOWNLOAD? 
//Other Get Set Methods... 

} 

} 

También cómo puedo pasar tanto tiempo a la identificación managedBean del JSF desde dentro de un commandButton? Está permitido?

<!-- How to pass the value of id from --> 
<h:commandButton action="downloadController.startDownload(#{garbage.id})"> 

Respuesta

10

Paso de parámetros en El sólo funciona cuando el web.xml está declarada como Servlet 3.0 y el servletcontainer también soporta (3 Glassfish, JBoss AS 6, 7 Tomcat, etc). Sólo hay un error de sintaxis en su intento, esta es la forma correcta:

<h:commandButton action="#{downloadController.startDownload(garbage.id)}" /> 

Incluso puede pasar objetos a lo largo de todo, eso es mejor en este caso particular.

<h:commandButton action="#{downloadController.startDownload(garbage)}" /> 

Entonces, el método startDownload() debe establecer las cabeceras de respuesta para que el navegador web entiende lo que el tipo de contenido del cuerpo de la respuesta representa y qué hacer con él y finalmente escribir el contenido del cuerpo de la respuesta. Puede hacerlo todo con la ayuda de ExternalContext. Aquí está un ejemplo patada de salida:

public void startDownload(Garbage garbage) { 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    ExternalContext externalContext = facesContext.getExternalContext(); 
    externalContext.setResponseHeader("Content-Type", garbage.getContentType()); 
    externalContext.setResponseHeader("Content-Length", garbage.getContent().length); 
    externalContext.setResponseHeader("Content-Disposition", "attachment;filename=\"" + garbage.getFileName() + "\""); 
    externalContext.getResponseOutputStream().write(garbage.getContent()); 
    facesContext.responseComplete(); 
} 

La última línea con FacesContext#responseComplete() es obligatorio para que JSF entiende que no debe desplazarse hasta cierto punto de vista y por lo tanto potencialmente malform la respuesta con otra página JSF después.

+0

Qué debe contener ContentType si se trata de un archivo .doc. ¿Debería ese método getContentType() devolver "text/xml" o "text/plain"? – sfrj

+2

Oh, un documento de Word ciertamente no es un archivo de texto. Para '.doc' es' application/msword' y para '.docx' es' application/vnd.openxmlformats-officedocument.wordprocessingml.document'. Puede usar 'ServletContext # getMimeType()' si desea determinarlo programáticamente en función del nombre del archivo. Ver también http://stackoverflow.com/questions/2426773/when-do-browsers-send-application-octet-stream-as-content-type/2426952#2426952 – BalusC

+0

Gracias, lo intentaré – sfrj

Cuestiones relacionadas