JSF实现文件上传

 目前 JSF 对于档案上传的支持很差,JSC 内更是缺少档案上传的组件
除非使用 Orcale ADF 的组件,但是 Oracle ADF 并非免费的。
本篇文章主要就是跟大家分享如何在 JSF 内使用免费的 Jakarta Commons FileUpload (http://jakarta.apache.org/commons/fileupload/ ) 组件来实作档案上传功能。
有几点注意事项,这边必须先要提出的:
1. Servlet 部分改自本讨论区 JiaYun 大大的「档案上传 JSP 小范例」,希望他不会介意!^^" (如果需要更清楚的 Jakarta Commons FileUpload 范例,那篇文章

会是更好的选择。)
2. 档案上传,必须把 form 的 enctype 更改如下:

<h:form binding="#{AttachFile.form1}" enctype="multipart/form-data" id="form1">


但是以上的 JSF 标签 compile 都会正常,但是在这个 form 里面,其它组件的 action 都会无法正常触发。所以这边仅使用一般的 JSP 页面。
3. 这篇献丑的教学其实是使用 JSF(其它页面) -> JSP(选择档案页面) -> Servlet(储存使用者上传的档案) -> JSF(其它页面) 的流程。
说穿了,只是使用旧的 JSP + Servlet 技术,请各位高手海涵。

 流程一(选择档案的 JSP 页面):

<f:verbatim>
     <form action="UploadFile" enctype="multipart/form-data" method="post">
       File:<input name="txtFile" type="file"/><br/>                       
       Description:<input name="txtDesc" type="text"/><br/>
       <input type="checkbox" name="chkAdd"/>Add another file<br/>
       <input style="height: 27px; left: 0px; top: 96px; position: absolute; width: 72px" type="submit" value="Add"/>
       <input style="height: 27px; left: 96px; top: 96px; position: absolute; width: 72px" type="submit" value="Cancel"/>
     </form>
</f:verbatim>               
<h:form binding="#{AttachFile.form1}" id="form1"/>

 1. 这个页面包含:
一个 type="file" 的 textbox
一个一般的 textbox 提供为输入档案描述
一个 checkbox,提供多重上传档案
一个 Add 及一个 Cancel 的 Button
2. 如果使用者选取 checkBox,在后面的 Servlet 处理完,则回到这一页 ,选择另一个上传的档案。 如果没有勾选,则前进到其它的 JSF 页面。
3. UploadFile 为后面要处理档案储存的 Servlet 名称。
4. 以上只写出修改的地方,其它 JSF 预设的 tag 就不写出来了。

 流程二(web.xml):
<servlet>
     <servlet-name>Upload_File</servlet-name>
     <servlet-class>webapplication1.UploadFile</servlet-class>
</servlet>
<servlet-mapping>
     <servlet-name>Upload_File</servlet-name>
     <url-pattern>/UploadFile</url-pattern>
</servlet-mapping>
1. 请把这一段程序代码与 web.xml 内的其它 servlet tag 放在一块,比较不会出问题。
2. 这段大致的意义为:当你向 server 要求 /UploadFile 这个 URL 时, server 会使用 webapplication1.UploadFile 这个 servlet 来处理你的要求。

 流程三(后端处理档案的 Servlet):
UploadFile
import java.io.*;
import java.util.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;

public class UploadFile extends HttpServlet{
       public void doPost(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException {
         //取得 JSF 的 SessionBean
         SessionBean1 sesBean=(SessionBean1)servletRequest.getSession().getAttribute("SessionBean1");
         //取得 JSF 的 ApplicationBean
         ApplicationBean1 appBean=(ApplicationBean1)getServletContext().getAttribute("ApplicationBean1");
         // 宣告将上传之档案放置到服务器的 / .... /upload 目录中
         //String saveDirectory = appBean.getAttachPath();
         // 宣告暂存目录
         //String tmpDirectory = "c:\\";
         // 宣告限制上传之档案总大小为, 单位为 byte, -1 表示无限制
         int maxPostSize = -1;
         // 宣告储存叙述上传档案内容的变量
         String FileDescription = "";
         // 宣告是否接下来要继续新增档案
         boolean hasMore = false;
         // 宣告储存上传文件名称的变量
         String FileName = "";
         // 宣告储存上传档案大小的变量
         long FileSize = 0;
         // 宣告储存上传档案型态的变量
         //String ContentType = null;
         // 计算上传档案之个数
         int count = 0 ;

         try {
           DiskFileUpload upload = new DiskFileUpload();
           // 处理中文档名问题
           upload.setHeaderEncoding("UTF-8");
           // 设定内存存放数据的大小, 超过则写入档案, 有设定暂存目录, 暂存盘置于暂存目录下
           //upload.setSizeThreshold(4096);
           // 设定总上传大小限制
           //upload.setSizeMax(maxPostSize);
           // 设定暂存目录
           //upload.setRepositoryPath(tmpDirectory);
           List items =upload.parseRequest((HttpServletRequest)servletRequest);
           Iterator iter = items.iterator();
           FileItem fItem=null;
       
           while(iter.hasNext()) {
                   FileItem item = (FileItem) iter.next();
                   if (item.isFormField()) {
                       // 一般字段
                       if(item.getFieldName().equalsIgnoreCase("txtDesc")) {
                           // 取得档案叙述
                           FileDescription = item.getString("UTF-8");
                       }
                       else if(item.getFieldName().equalsIgnoreCase("chkAdd")) {
                           // 取得接下来将前往的页面
                           hasMore = item.getString().equalsIgnoreCase("on") ? true: false;
                       }
                   }
                   else {
                       // 档案字段
                       // 否则取得档案信息
                       FileName = item.getName();
                       // 因为不同的浏览器会造成传递 path + filename, 有些则只有 filename
                       // for wintel platform
                       FileName = FileName.substring(FileName.lastIndexOf("\\")+1);
                       // for unix-like platform
                       FileName = FileName.substring(FileName.lastIndexOf("/")+1);
                   
                       //ContentType = item.getContentType();
                       FileSize = item.getSize();                   
                   
                       fItem=item;
                   }
               }

               //--Delete--
               //如果需要的话
               //你可以在这里使用前面取得的 SessionBean 及 ApplicationBean
               //里面的参数对你的数据库做操作,并把档案描述在这里存入数据库
           
               //写入档案
               File uploadedFile = new File(appBean.getAttachPath() + FileName);
               fItem.write(uploadedFile);           
           }
           catch(Exception ex) {
             //例外处理           
           }
           //导向不同的页面
           finally {
               if(hasMore)
                   servletResponse.sendRedirect("faces/AttachFile.jsp");
               else
                   servletResponse.sendRedirect("faces/Schedule.jsp");
           }
       }
}
1. 前面的取得 SessionBean1 及 ApplicationBean1,看个人需要,如果你需要取得 JSF 内的 SessionBean 及 ApplicationBean,可以参考这个用法。
2. 最后的 servletResponse.sendRedirect 会根据前面的 JSP 页面,是否有勾选 chkAdd 来决定是要回到前面的 JSP 页面来继续新增档案,或是前往其它 JSF 页面。
3. 请注意 faces/Schedule.jsp 前面的 faces ,如果不加可能可会出现 Cannot find FacesContext 的错误。

你可能感兴趣的:(JSF)