以下文章展示了如何在seam中上传下载附件。
开始:
用'seam create-entity'命令,或用 JBoss Tools ,在项目上单击右键,然后"New -> Seam Entity" ,Entity 名为"Attachment"。我们仅用部分生成代码,只是为了在正确的位置建立相应文件,这样可以不必担心文件位置。
下一步,修改 Attachment.java :
import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Lob; @Entity public class Attachment implements java.io.Serializable { @Id @GeneratedValue private Long id; public Long getId() { return this.id; } public void setId(Long id) { this.id = id; } private String name; public String getName() { return this.name; } public void setName(String name) { this.name = name; } private long size; public long getSize() { return this.size; } public void setSize(long size) { this.size = size; } private String contentType; public String getContentType() { return this.contentType; } public void setContentType(String contentType) { this.contentType = contentType; } @Lob @Column(length = 2147483647) @Basic(fetch = FetchType.LAZY) private byte[] data; public byte[] getData() { return this.data; } public void setData(byte[] data) { this.data = data; } }
现在它已经包含了与s:fileUpload对应的全部字段。
打开 attachment.xhtml ,编辑内容为:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml"> <ui:define name="body"> <h:messages globalOnly="true" styleClass="message" /> <h:form enctype="multipart/form-data"> <rich:panel> <f:facet name="header">Upload Attachment</f:facet> <s:decorate id="fileUploadDecoration" template="layout/edit.xhtml"> <ui:define name="label">Attachment</ui:define> <s:fileUpload id="file" data="#{attachmentHome.instance.data}" contentType="#{attachmentHome.instance.contentType}" fileName="#{attachmentHome.instance.name}" fileSize="#{attachmentHome.instance.size}" /> </s:decorate> <s:decorate id="nameDecoration" template="layout/display.xhtml"> <ui:define name="label">Name</ui:define> <h:outputText value="#{attachmentHome.instance.name}"/> </s:decorate> <s:decorate id="contentTypeDecoration" template="layout/display.xhtml"> <ui:define name="label">Content Type</ui:define> <h:outputText value="#{attachmentHome.instance.contentType}"/> </s:decorate> <s:decorate id="sizeDecoration" template="layout/display.xhtml"> <ui:define name="label">Size</ui:define> <h:outputText value="#{attachmentHome.instance.size}"/> </s:decorate> <div style="clear: both" mce_style="clear: both" /> </rich:panel> <div class="actionButtons"> <h:commandButton value="Upload" action="#{attachmentHome.persist}" rendered="#{!attachmentHome.managed}"/> <h:commandButton value="Delete" action="#{attachmentHome.remove}" immediate="true" rendered="#{attachmentHome.managed}"> <s:conversationPropagation type="end" /> </h:commandButton> <s:button propagation="end" id="done" value="Done" view="/attachmentList.xhtml"/> </div> </h:form> </ui:define> </ui:composition>
以上代码与 CRUD 页面的主要区别是,字段是输出文本而非输入,因为字段值由 s:fileUpload component 自动确定。这里的代码你可以随便修改。
继续修改 attachmentList.xhtml ,使其可以显示上传文件的属性,并且允许下载:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml"> <ui:define name="body"> <h:messages globalOnly="true" styleClass="message"/> <rich:panel> <f:facet name="header">Files Uploaded</f:facet> <div class="results"> <h:outputText value="No files exists" rendered="#{empty attachmentList.resultList}"/> <rich:dataTable id="attachmentList" var="attachment" value="#{attachmentList.resultList}" rendered="#{not empty attachmentList.resultList}"> <rich:column> <f:facet name="header">File Name</f:facet> <s:link value="#{attachment.name}" view="/attachment.xhtml"> <f:param name="attachmentId" value="#{attachment.id}" /> </s:link> </rich:column> <rich:column> <f:facet name="header">Content Type</f:facet> #{attachment.contentType} </rich:column> <rich:column> <f:facet name="header">Size(bytes)</f:facet> #{attachment.size} </rich:column> <rich:column> <f:facet name="header">Action</f:facet> <s:link value="Download" action="#{downloadAttachment.download}"> <f:param name="attachmentId" value="${attachment.id}" /> </s:link> </rich:column> </rich:dataTable> </div> </rich:panel> <div class="actionButtons"> <s:button id="done" value="Create attachment" view="/attachment.xhtml"/> </div> </ui:define> </ui:composition>
这里有一个名为 downloadAttachment 的Component,引用了我们还没创建的内容,所以,我们先来建立它。你可以用EJB3 或者 Seam pojo,下面的工作好简单,我们继续。DownloadAttachment 组件是本文的核心,所以要注意了:
@Name("downloadAttachment") public class DownloadAttachment { @Logger private Log log; @In private EntityManager entityManager; @In(value="#{facesContext.externalContext}") private ExternalContext extCtx; @In(value="#{facesContext}") FacesContext facesContext; @RequestParameter private Long attachmentId; public String download() { Attachment attachment = entityManager.find(Attachment.class, attachmentId); HttpServletResponse response = (HttpServletResponse)extCtx.getResponse(); response.setContentType(attachment.getContentType()); response.addHeader("Content-disposition", "attachment; filename=/"" + attachment.getName() +"/""); try { ServletOutputStream os = response.getOutputStream(); os.write(attachment.getData()); os.flush(); os.close(); facesContext.responseComplete(); } catch(Exception e) { log.error("/nFailure : " + e.toString() + "/n"); } return null; } }