文/陶刚编译
示例应用程序
前面的部分介绍了是MyFaces如何在通用文件上载的帮助下支持文件上载的。现在我们来看一个实际的利用了这种特性的应用程序。JSF窗体(MyForm.jsp)让用户选择一个文件和一个报文摘要算法,后台bean( MyBean.java)使用这个算法计算出一个散列值,显示在另外一个web页面(MyResult.jsp)中。这些页面和后台bean通过一个JSF配置文件(faces-config.xml)结合在一起。
MyForm.jsp页面
这个JSF窗体使用了MyFaces的<x:inputFileUpload>标记,同时还使用了其它一些标准的JSF标记来呈现标签、消息、包含报文摘要算法的下拉列表、使用JSF表达式(#{myBean.processMyFile})指定了处理被上载文件的操作方法的命令按钮:
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <%@ taglib uri="http://myfaces.apache.org/extensions" prefix="x"%>
<f:view> <h:form id="MyForm" enctype="multipart/form-data" > <h:messages globalOnly="true" styleClass="message"/> <h:panelGrid columns="3" border="0" cellspacing="5"> <h:outputLabel for="myFileId" value="File: "/> <x:inputFileUpload id="myFileId" value="#{myBean.myFile}" storage="file" required="true"/> <h:message for="myFileId"/> <h:outputLabel for="myParamId" value="Param: "/> <h:selectOneMenu id="myParamId" value="#{myBean.myParam}" required="true"> <f:selectItem itemLabel="" itemValue=""/> <f:selectItem itemLabel="MD5" itemValue="MD5"/> <f:selectItem itemLabel="SHA-1" itemValue="SHA-1"/> <f:selectItem itemLabel="SHA-256" itemValue="SHA-256"/> <f:selectItem itemLabel="SHA-384" itemValue="SHA-384"/> <f:selectItem itemLabel="SHA-512" itemValue="SHA-512"/> </h:selectOneMenu> <h:message for="myParamId"/>
<h:outputText value=" "/> <h:commandButton value="Submit" action="#{myBean.processMyFile}"/> <h:outputText value=" "/>
</h:panelGrid> </h:form> </f:view> | MyBean类
后台bean拥有三个属性:myFile、myParam和myResult。前面已经解释了myFile属性的角色。它让你获取被上载文件的内容和文件名、文件大小、内容类型。myParam属性的值是报文摘要算法。myResult属性将保存processMyFile()方法执行之后的散列值。MyBean类为自己的所有属性提供了get和set方法:
package com.devsphere.articles.jsfupload;
import org.apache.myfaces.custom.fileupload.UploadedFile; ... public class MyBean { private UploadedFile myFile; private String myParam; private String myResult;
public UploadedFile getMyFile() { return myFile; }
public void setMyFile(UploadedFile myFile) { this.myFile = myFile; }
public String getMyParam() { return myParam; }
public void setMyParam(String myParam) { this.myParam = myParam; }
public String getMyResult() { return myResult; }
public void setMyResult(String myResult) { this.myResult = myResult; } ... } | processMyFile()通过一个输入流获取被上载文件的内容,这个输入流是通过myFile.getInputStream()获得的。散列值是在java.security.MessageDigest的帮助下计算出来的,然后把它转换为字符串,这样就可以被myResult属性访问了:
package com.devsphere.articles.jsfupload; ... import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext;
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException;
import java.io.*;
public class MyBean { ... public String processMyFile() { try { MessageDigest md= MessageDigest.getInstance(myParam); InputStream in = new BufferedInputStream( myFile.getInputStream()); try { byte[] buffer = new byte[64 * 1024]; int count; while ((count = in.read(buffer)) > 0) md.update(buffer, 0, count); } finally { in.close(); } byte hash[] = md.digest(); StringBuffer buf = new StringBuffer(); for (int i = 0; i < hash.length; i++) { int b = hash[i] & 0xFF; int c = (b >> 4) & 0xF; c = c < 10 ? ’0’ + c : ’A’ + c - 10; buf.append((char) c); c = b & 0xF; c = c < 10 ? ’0’ + c : ’A’ + c - 10; buf.append((char) c); } myResult = buf.toString(); return "OK"; } catch (Exception x) { FacesMessage message = new FacesMessage( FacesMessage.SEVERITY_FATAL, x.getClass().getName(), x.getMessage()); FacesContext.getCurrentInstance().addMessage(null, message); return null; } }
} | faces-config.xml文件
JSF配置文件把后台bean定义在request作用域中,并且指定了一个导航规则:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
<managed-bean> <managed-bean-name>myBean</managed-bean-name> <managed-bean-class> com.devsphere.articles.jsfupload.MyBean </managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean>
<navigation-rule> <from-view-id>/MyForm.jsp</from-view-id> <navigation-case> <from-outcome>OK</from-outcome> <to-view-id>/MyResult.jsp</to-view-id> </navigation-case> </navigation-rule>
</faces-config> | MyResult.jsp页面
这个web页面显示了被上载文件的一些信息:
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<f:view>
<h:panelGrid columns="2" border="0" cellspacing="5">
<h:outputText value="FileName:"/> <h:outputText value="#{myBean.myFile.name}"/>
<h:outputText value="FileSize:"/> <h:outputText value="#{myBean.myFile.size}"/>
<h:outputText value="Param:"/> <h:outputText value="#{myBean.myParam}"/>
<h:outputText value="Result:"/> <h:outputText value="#{myBean.myResult}"/>
</h:panelGrid>
</f:view> | 被显示的文件名可能带有客户端文件系统的完整路径,如下所示:
图2:结果页面产生的输出信息 | 总结
在很多情况下,用户需要通过浏览器上载文件,但是在服务器端却没有处理这些文件的理想方法。把文件的内容保存在内存中对于小型文件来说是可以接受的,但是把被上载的文件存储在临时文件中使这种情况变复杂了。MyFaces让你能够选择一个适合应用程序需求的解决方案,但是这个框架组件也有一些小问题。当你不再需要临时文件的时候,它无法让你删除它们;文件名有时候带有文件路径;当用户上载过大的文件的时候也没有警告信息。这些缺陷是可以修补的,因为我们可以使用源代码,而且本文就介绍了MyFaces代码可以改进的一些的地方。无论如何,对于多数应用程序来说,MyFaces不做修改就合乎需求。本文的例子是使用JSF 1.1.01、MyFaces 1.0.9和通用文件上载1.0环境测试的。
[上一页] [1] [2] [3]
|