JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Web Framework » JSF  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 在 JSF 實作檔案上傳(File Upload) [精華]
CMHuang

妳喜歡我的大象嗎?(羞)

版主

發文: 81
積分: 4
於 2005-03-28 15:56 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
目前 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 更改如下:
1
<h:form binding="#{AttachFile.form1}" enctype="multipart/form-data" id="form1">                    

但是以上的 JSF 標籤 compile 都會正常,但是在這個 form 裡面,其他元件的 action 都會無法正常觸發。所以這邊僅使用一般的 JSP 頁面。

3. 這篇獻醜的教學其實是使用 JSF(其他頁面) -> JSP(選擇檔案頁面) -> Servlet(儲存使用者上傳的檔案) -> JSF(其他頁面) 的流程。
說穿了,只是使用舊的 JSP + Servlet 技術,請各位高手海涵。

流程一(選擇檔案的 JSP 頁面):
1
2
3
4
5
6
7
8
9
10
<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):
1
2
3
4
5
6
7
8
<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):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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 的錯誤。


CMHuang edited on 2005-03-29 21:03
reply to postreply to post
作者 Re:在 JSF 實作檔案上傳 [Re:CMHuang]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2005-03-28 18:13 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
舊的MyFaces網站好像也有檔案上傳元件。。。不過沒用過。。。不確定好不好用。。。

http://www.myfaces.org/


reply to postreply to post
良葛格學習筆記
作者 Re:在 JSF 實作檔案上傳 [Re:caterpillar]
javaer

OMG!



發文: 87
積分: 1
於 2005-03-28 20:48 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
我前一陣子在看smartupload的程式碼
不知道是不是因為用dj的關係
發現它的程式碼實在是...
如果大家有需要的話,等我整理好再上傳
它可以做上、下傳,而且沒有中文的問題
只是跟jakart的元件相比,實在是有點上不了檯面...

p.s.我修正了它的一點小問題,再做一點最佳化


reply to postreply to post
作者 Re:在 JSF 實作檔案上傳 [Re:CMHuang]
koji

秒速5センチメートル

站長

發文: 8415
積分: 19
於 2005-03-29 01:56 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
今天為了測一下自己觀念,順便那時沒翻到myfaces所以也實作了一個upload
觀念其實蠻簡單的,其實就是有人要求想在jsp頁面用到jsf元件,卻又想在同個頁面塞
檔案上傳.

所以實作上我做成
jsf->filter->jsf servler->backing bean

其實就是在filter內把檔案上傳解決以後,
新增一個自己做的requestWrapper.
讓jsf servler誤以為這個wrapper是真的request.
就大功告成拉!!!

只是程式碼很醜,有時間稍微整理整理在放上來Tongue

koji


browser edited on 2005-03-29 09:29
reply to postreply to post
JCConf Taiwan 2015 開始售票了!!
Facebook上的TWJUG社團,歡迎加入
作者 Re:在 JSF 實作檔案上傳 [Re:CMHuang]
CMHuang

妳喜歡我的大象嗎?(羞)

版主

發文: 81
積分: 4
於 2005-03-29 17:53 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
今天測試了一下
原本的程式在 JSC 內附的 SunAppServer8,中文會有問題。
所以我又改了兩行來解決中文的問題:
1
2
upload.setHeaderEncoding("UTF-8"); //中文檔名 
FileDescription = item.getString("UTF-8");  //其他中文欄位


附帶一提,如果使用
1
FileDescription = new String(item.getString().getBytes(), "UTF-8");

來轉換編碼,可能會變成亂碼唷!


CMHuang edited on 2005-03-29 18:04
reply to postreply to post
» JWorld@TW »  Web Framework » JSF

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8