当前位置: 首页 > 面试题库 >

如何使用JSF 2.0下载存储在数据库中的文件

潘衡
2023-03-14
问题内容

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

这是我用来从db返回byte []的查询:

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

}

}

另外,如何从命令按钮中从JSF将该长id传递给ManagedBean?可以吗?

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

问题答案:

仅当将web.xml声明为Servlet 3.0并且servlet容器也支持它时,在EL中传递参数才有效(Glassfish 3,JBoss AS
6,Tomcat 7等)。尝试中只有语法错误,这是正确的方法:

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

您甚至可以传递整个对象,在这种情况下更好。

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

然后,该startDownload()方法应设置响应头,以便Web浏览器了解响应主体表示什么内容类型以及如何处理它,最后将内容写入响应主体。您可以在的帮助下完成所有操作ExternalContext。这是一个启动示例:

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

最后一行带有FacesContext#responseComplete()强制性,因此JSF理解它不应导航到某些视图,因此可能在随后的另一个JSF页面中使响应格式错误。



 类似资料: