如何使用JSF 2.0下载存储在数据库中的文件 [英] How to download a file stored in a database with JSF 2.0

查看:156
本文介绍了如何使用JSF 2.0下载存储在数据库中的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要下载存储在数据库中的文件。我想我做的正确的查询,并称它,我只是不知道如何连接到JSF页面中的按钮。
另外我想知道,我必须将该图像保存在服务器的文件夹中,然后再传递给JSF页面。如果是这样,我该怎么做?

I need to download a file stored in a database. I think i did correctly the query and called it i just dont know how can i connect that to a button in a JSF page. Also i am wondering, do i have to save that image in a folder at the server before passing it to the JSF page. If so, How can i do that?

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

This is the query i use to return the byte[] from the db:

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

Here is a simple EJB that calls that query then get the 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?

Now this is the part that confuses me, how can i that above with the JSF page and managed 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传递那个long id到managedBean?这是否允许?

Also how can i pass that long id to the managedBean from the JSF from within a commandButton? Is this allowed?

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


推荐答案

通过EL中的参数仅在 web.xml 被声明为Servlet 3.0,servletcontainer也支持它(Glassfish 3,JBoss AS 6,Tomcat 7等)。你的尝试只有一个语法错误,这是正确的方法:

Passing parameters in EL only works when the web.xml is declared as Servlet 3.0 and the servletcontainer also supports it (Glassfish 3, JBoss AS 6, Tomcat 7, etc). There's only a syntax error in your attempt, here's the correct way:

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

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

You can even pass whole objects along, that's better in this particular case.

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

然后, startDownload()设置响应标头,以便web浏览器了解响应体表示什么内容类型,以及如何处理响应头,最后将内容写入响应主体。您可以通过 的ExternalContext 。这是一个开球示例:

Then, the startDownload() method should set the response headers so that the webbrowser understands what content type the response body represents and what to do with it and finally write the content to the response body. You can do it all with help of ExternalContext. Here's a kickoff example:

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() / a>是强制性的,因此JSF了解到它不应该导航到某些视图,从而可能会在另一个JSF页面之后导致响应错误。

The last line with FacesContext#responseComplete() is mandatory so that JSF understands that it shouldn't navigate to some view and thus potentially malform the response with another JSF page afterwards.

这篇关于如何使用JSF 2.0下载存储在数据库中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆