2011-03-31 25 views
5

Veritabanında saklanan bir dosyayı indirmem gerekiyor. Sanırım sorguyu doğru bir şekilde yaptım ve onu sadece JSF sayfasındaki bir düğmeye nasıl bağlayabileceğimi bilmiyorum. Ayrıca merak ediyorum, bu resmi JSF sayfasına iletmeden önce sunucudaki bir klasöre kaydetmek zorunda mıyım? Eğer öyleyse, bunu nasıl yapabilirim? Şimdi buJSF 2.0 ile veritabanında saklanan bir dosya nasıl karşıdan yüklenir

@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; 
} 

: Burada

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

bu sorgu ardından kimliği almak çağıran basit EJB:

Bu

i db byte [] dönmek için kullandıkları sorgu Beni şaşkına getiren bölüm, yukarıdaki JSF sayfası ve yönetilen fasulye ile nasıl yapabilirim? i geçebilir nasıl da

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

} 

} 

bir KomutDüğmesi içinden JSF managedBean uzun id? Bu izin verilir mi? web.xml Servlet 3.0 olarak ilan ve servletcontainer da onu destekleyen olduğunda EL

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

cevap

10

Geçme parametreleri yalnızca (6, Tomcat 7, vs AS glassfish 3, JBoss) çalışır. Sadece bir sözdizimi hatası burada doğru yoldur, girişiminizde var: Hatta boyunca bütün nesneleri geçebilir

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

, bu özel durumda daha iyi. webbrowser içerik yanıtı vücut temsil yazıp onunla ne yapacağını ve nihayet yanıt gövdesinde içerik yazma anlayan böylece

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

Sonra startDownload() yöntem yanıt başlıklarını koymalıdır. Hepsini ExternalContext yardımıyla yapabilirsiniz. MTU bazı görünüme gidin ve böylece potansiyel olarak sonradan başka JSF sayfasıyla tepkisini kusurlu hale gerektiğini anlaması için

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() ile son satırı zorunludur: İşte başlama örnek.

+0

Bir .doc dosyası ise ContentType olması gerekir. Bu yöntem getContentType() "text/xml" veya "text/plain" döndürüyor mu? – sfrj

+2

Oh, bir Word belgesi kesinlikle bir metin dosyası değildir. '.doc' için' application/msword' ve '.docx' için' application/vnd.openxmlformats-officedocument.wordprocessingml.document' dir. Program ismini dosya adına göre belirlemek istiyorsanız 'ServletContext # getMimeType()' ı kullanabilirsiniz. Ayrıca bkz. Http://stackoverflow.com/questions/2426773/when-do-browsers-send-application-octet-stream-as-content-type/2426952#2426952 – BalusC

+0

Teşekkürler. – sfrj

İlgili konular