Java 如何使用JSF2.0下载存储在数据库中的文件

Java 如何使用JSF2.0下载存储在数据库中的文件,java,jsf,jpa,jakarta-ee,download,Java,Jsf,Jpa,Jakarta Ee,Download,我需要下载一个存储在数据库中的文件。我想我正确地执行了查询并调用了它,我只是不知道如何将它连接到JSF页面中的按钮。 我还想知道,在将该图像传递到JSF页面之前,是否必须将其保存在服务器的文件夹中。如果是,我该怎么做 这是我用来从数据库返回字节[]的查询: @NamedQuery(name = "downloadGarbage", query = "SELECT g.file FROM Garbage g WHERE g.id :idParam") @Entity public class Ga

我需要下载一个存储在数据库中的文件。我想我正确地执行了查询并调用了它,我只是不知道如何将它连接到JSF页面中的按钮。 我还想知道,在将该图像传递到JSF页面之前,是否必须将其保存在服务器的文件夹中。如果是,我该怎么做

这是我用来从数据库返回字节[]的查询:

@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;
....
下面是一个简单的EJB,它调用该查询,然后获取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;
}
现在这是让我困惑的部分,我怎么能用JSF页面和托管bean来实现上面的内容呢

@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...

}

}
另外,我如何从commandButton中从JSF将长id传递给managedBean?允许这样做吗

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

仅当
web.xml
声明为Servlet 3.0且servletcontainer也支持它时,在EL中传递参数才有效(Glassfish 3、JBoss as 6、Tomcat 7等)。您的尝试中只有一个语法错误,以下是正确的方法:

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

带有的最后一行是必需的,这样JSF就知道它不应该导航到某个视图,因此可能会在以后使用另一个JSF页面错误地生成响应。

如果是.doc文件,那么ContentType应该是什么。该方法getContentType()是否应返回“text/xml”或“text/plain”?噢,Word文档肯定不是文本文件。对于
.doc
而言,它是
应用程序/msword
;对于
.docx
而言,它是
应用程序/vnd.openxmlformats of cedocument.wordprocessingml.document
。如果希望根据文件名以编程方式确定它,可以使用
ServletContext#getMimeType()
。另见
<h:commandButton action="#{downloadController.startDownload(garbage)}" />
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();
}