
<form enctype="multipart/form-data" method="post" action="...">
...
<input type="file" name="...">
...
</form>
  但是事情并非這么簡單,因為實現servlet和jsp規范的應用程序服務器不一定能夠處理multipart/form-data編碼方式。因此,你必須分析請求的輸入流,例如apache通用文件上載就是一個小型的java程序包,它讓你能夠從編碼的數據中獲取被上載文件的內容。這個程序包的api是很靈活的,它允許你把小文件存儲在內存中,把大文件存儲在磁盤的臨時目錄中。你可以指定一個文件大小的閥值,大于這個值的文件都會被寫到磁盤上,而不會保留在內存中,而且你還可以規定允許的被上載文件的最大大小。
  前面提到的org.apache.commons.fileupload程序包包含一個叫作diskfileupload的類,它的parserequest()方法獲取httpservletrequest參數,并返回org.apache.commons.fileupload.fileitem實例列表。編碼后的窗體數據從servlet請求的getinputstream()方法所返回的數據流流中讀取。fileitem這個名字容易使人誤解,因為這個接口的實例同時表現了被上載的文件和正常的請求參數。
  通用文件上載程序包所提供的api賦予了你訪問分解后的窗體數據的權利,但是servlet請求的getparameter()和getparametervalues()方法卻無法工作。這是一個難題,因為在輸入字段、檢查框、單選框和列表框后臺運行的jsf組件需要調用這兩個方法。我們可以利用servlets api提供的兩個特性(過濾器和請求包裝器)來解決這個問題。下一部分描述了apache myfaces如何實現過濾器,添加了大量必要的對文件上載的支持,而不會中斷已有的jsf組件。此外,myfaces為javabeans提供了api,同時還提供了一個定制的jsf組件,它表現為<input type="file">元素。
  配置jsf和myfaces擴展
  目前,jsf規范的主要實現是jsf參考實現(ri),與此同時,apache提供了另外一個實現,就是myfaces。當然可能存在其它一些jsf實現,但是jsf ri和myfaces是其中最流行的兩個。很多開發者更喜歡前者,因為sun把它稱為"官方的"實現,但是,myfaces擁有一些有趣的擴展(例如對上載文件操作的支持)。如果你愿意,可以把myfaces擴展與sun的jsf ri一起使用。你只需要把myfaces-extensions.jar文件、jsf ri的jar文件和commons-fileupload-1.0.jar文件一起放到自己的web應用程序的web-inf/lib目錄中就可以了。下面是需要的jar文件:
jsf 1.1 ri jsf-api.jarjsf-impl.jar
jstl 1.1 ri jstl.jarstandard.jar
myfaces擴展 myfaces-extensions.jar
apache commons(供jsf和myfaces 擴展使用) commons-collections.jarcommons-digester.jarcommons-beanutils.jarcommons-logging.jarcommons-fileupload-1.0.jar
<?xml version="1.0" encoding="utf-8"?>
<!doctype web-app public
"-//sun microsystems, inc.//dtd web application 2.3//en"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<param-name>javax.faces.state_saving_method</param-name>
<param-value>client</param-value>
</context-param>
<servlet>
<servlet-name>facesservlet</servlet-name>
<servlet-class>
javax.faces.webapp.facesservlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>facesservlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>facesservlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<filter>
<filter-name>extensionsfilter</filter-name>
<filter-class>
org.apache.myfaces.component.html.util.extensionsfilter
</filter-class>
<init-param>
<param-name>uploadmaxfilesize</param-name>
<param-value>10m</param-value>
</init-param>
<init-param>
<param-name>uploadthresholdsize</param-name>
<param-value>100k</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>extensionsfilter</filter-name>
<servlet-name>facesservlet</servlet-name>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
<%@ 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" >
...
<x:inputfileupload id="myfileid"
value="#{mybean.myfile}"
storage="file"
required="true"/>
...
</h:form>
</f:view>
import org.apache.myfaces.custom.fileupload.uploadedfile;
...
public class mybean {
private uploadedfile myfile;
public uploadedfile getmyfile() {
return myfile;
}
public void setmyfile(uploadedfile myfile) {
this.myfile = myfile;
}
...
}
  示例應用程序
  前面的部分介紹了是myfaces如何在通用文件上載的幫助下支持文件上載的?,F在我們來看一個實際的利用了這種特性的應用程序。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"/>
?。糷:panelgrid columns="3" border="0" cellspacing="5">
?。糷:outputlabel for="myfileid" value="file: "/>
?。紉:inputfileupload id="myfileid" value="#{mybean.myfile}" storage="file" required="true"/>
?。糷:message for="myfileid"/>
?。糷:outputlabel for="myparamid" value="param: "/>
?。糷:selectonemenu id="myparamid" value="#{mybean.myparam}" required="true">
 <f:selectitem itemlabel="" itemvalue=""/>
 <f:selectitem itemlabel="md5" itemvalue="md5"/>
?。糵: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>
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;
 }
 ...
}
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;
 }
}
}
<?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>
<%@ 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>

新聞熱點
疑難解答