轉:在Struts 2中實現檔案上傳

來源:互聯網
上載者:User

標籤:style   blog   http   color   io   os   使用   ar   java   

前一陣子有些朋友在電子郵件中問關於Struts 2實現檔案上傳的問題, 所以今天我們就來討論一下這個問題。

實現原理

Struts 2是通過Commons FileUpload檔案上傳。Commons FileUpload通過將HTTP的資料儲存到臨時檔案夾,然後Struts使用fileUpload攔截器將檔案綁定到Action的執行個體中。從而我們就能夠以本地檔案方式的操作瀏覽器上傳的檔案。

具體實現

前段時間Apache發布了Struts 2.0.6 GA,所以本文的實現是以該版本的Struts作為架構的。以下是例子所依賴類包的列表:

 
清單1 依賴類包的列表

首先,建立檔案上傳頁面FileUpload.jsp,內容如下:

<% @ page language = " java " contentType = " text/html; charset=utf-8 " pageEncoding = " utf-8 " %> <% @ taglib prefix = " s " uri = " /struts-tags " %> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < html xmlns ="http://www.w3.org/1999/xhtml" > < head >     < title > Struts 2 File Upload </ title > </ head > < body >     < s:form action ="fileUpload" method ="POST" enctype ="multipart/form-data" >         < s:file name ="myFile" label ="Image File" />         < s:textfield name ="caption" label ="Caption" />                < s:submit />     </ s:form > </ body > </ html >

清單2 FileUpload.jsp

在FileUpload.jsp中,先將表單的提交方式設為POST,然後將enctype設為multipart/form-data,這並沒有什麼特別之處。接下來,<s:file/>標誌將檔案上傳控制項綁定到Action的myFile屬性。

其次是FileUploadAction.java代碼:

 
package tutorial; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class FileUploadAction extends ActionSupport {     private static final long serialVersionUID = 572146812454l ;     private static final int BUFFER_SIZE = 16 * 1024 ;         private File myFile;     private String contentType;     private String fileName;     private String imageFileName;     private String caption;         public void setMyFileContentType(String contentType) {         this .contentType = contentType;    }          public void setMyFileFileName(String fileName) {         this .fileName = fileName;    }              public void setMyFile(File myFile) {         this .myFile = myFile;    }          public String getImageFileName() {         return imageFileName;    }          public String getCaption() {         return caption;    }       public void setCaption(String caption) {         this .caption = caption;    }          private static void copy(File src, File dst) {         try {            InputStream in = null ;            OutputStream out = null ;             try {                                in = new BufferedInputStream( new FileInputStream(src), BUFFER_SIZE);                out = new BufferedOutputStream( new FileOutputStream(dst), BUFFER_SIZE);                 byte [] buffer = new byte [BUFFER_SIZE];                 while (in.read(buffer) > 0 ) {                    out.write(buffer);                }             } finally {                 if ( null != in) {                    in.close();                }                  if ( null != out) {                    out.close();                }             }         } catch (Exception e) {            e.printStackTrace();        }     }          private static String getExtention(String fileName) {         int pos = fileName.lastIndexOf( " . " );         return fileName.substring(pos);    }      @Override     public String execute()     {                imageFileName = new Date().getTime() + getExtention(fileName);        File imageFile = new File(ServletActionContext.getServletContext().getRealPath( " /UploadImages " ) + " / " + imageFileName);        copy(myFile, imageFile);         return SUCCESS;    }     }

  

清單3 tutorial/FileUploadAction.java

在FileUploadAction中我分別寫了setMyFileContentType、setMyFileFileName、setMyFile和setCaption四個Setter方法,後兩者很容易明白,分別對應FileUpload.jsp中的<s:file/>和<s:textfield/>標誌。但是前兩者並沒有顯式地與任何的頁面標誌綁定,那麼它們的值又是從何而來的呢?其實,<s:file/>標誌不僅僅是綁定到myFile,還有myFileContentType(上傳檔案的MIME類型)和myFileFileName(上傳檔案的檔案名稱,該檔案名稱不包括檔案的路徑)。因此,<s:file name="xxx" />對應Action類裡面的xxx、xxxContentType和xxxFileName三個屬性。

FileUploadAction作用是將瀏覽器上傳的檔案拷貝到WEB應用程式的UploadImages檔案夾下,新檔案的名稱是由系統時間與上傳檔案的尾碼組成,該名稱將被賦給imageFileName屬性,以便上傳成功的跳轉頁面使用。

下面我們就來看看上傳成功的頁面:

<% @ page language = " java " contentType = " text/html; charset=utf-8 " pageEncoding = " utf-8 " %> <% @ taglib prefix = " s " uri = " /struts-tags " %> <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > < html xmlns ="http://www.w3.org/1999/xhtml" > < head >     < title > Struts 2 File Upload </ title > </ head > < body >     < div style ="padding: 3px; border: solid 1px #cccccc; text-align: center" >         < img src =‘UploadImages/<s:property value ="imageFileName" /> ‘ />        < br />         < s:property value ="caption" />     </ div > </ body > </ html >

 

清單4 ShowUpload.jsp

ShowUpload.jsp獲得imageFileName,將其UploadImages組成URL,從而將上傳的映像顯示出來。

然後是Action的設定檔:

<? xml version="1.0" encoding="UTF-8" ?> <! DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd" > < struts >     < package name ="fileUploadDemo" extends ="struts-default" >         < action name ="fileUpload" class ="tutorial.FileUploadAction" >             < interceptor-ref name ="fileUploadStack" />             < result name ="success" > /ShowUpload.jsp </ result >         </ action >     </ package > </ struts >

  

清單5 struts.xml

fileUpload Action顯式地應用fileUploadStack的攔截器。

最後是web.xml設定檔:

<? xml version="1.0" encoding="UTF-8" ?> < web-app id ="WebApp_9" version ="2.4"     xmlns ="http://java.sun.com/xml/ns/j2ee"     xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >     < display-name > Struts 2 Fileupload </ display-name >     < filter >         < filter-name > struts-cleanup </ filter-name >         < filter-class >             org.apache.struts2.dispatcher.ActionContextCleanUp        </ filter-class >     </ filter >         < filter >         < filter-name > struts2 </ filter-name >         < filter-class >             org.apache.struts2.dispatcher.FilterDispatcher        </ filter-class >     </ filter >         < filter-mapping >         < filter-name > struts-cleanup </ filter-name >         < url-pattern > /* </ url-pattern >     </ filter-mapping >     < filter-mapping >         < filter-name > struts2 </ filter-name >         < url-pattern > /* </ url-pattern >     </ filter-mapping >     < welcome-file-list >         < welcome-file > index.html </ welcome-file >     </ welcome-file-list > </ web-app >

  

清單6 WEB-INF/web.xml

發布運行應用程式,在瀏覽器地址欄中鍵入:http://localhost:8080/Struts2_Fileupload/FileUpload.jsp,出現圖示頁面:

 
清單7 FileUpload頁面

選擇圖片檔案,填寫Caption並按下Submit按鈕提交,出現圖示頁面:

 
清單8 上傳成功頁面

更多配置

在運行上述例子,如果您留心一點的話,應該會探索服務器控制台有如下輸出:

Mar 20 , 2007 4 : 08 : 43 PM org.apache.struts2.dispatcher.Dispatcher getSaveDirINFO: Unable to find ‘struts.multipart.saveDir‘ property setting. Defaulting to javax.servlet.context.tempdirMar 20 , 2007 4 : 08 : 43 PM org.apache.struts2.interceptor.FileUploadInterceptor interceptINFO: Removing file myFile C:\Program Files\Tomcat 5.5 \work\Catalina\localhost\Struts2_Fileupload\upload_251447c2_1116e355841__7ff7_00000006.tmp

  

清單9 伺服器控制台輸出

上述資訊告訴我們,struts.multipart.saveDir沒有配置。struts.multipart.saveDir用於指定存放臨時檔案的檔案夾,該配置寫在struts.properties檔案中。例如,如果在struts.properties檔案加入如下代碼:

struts.multipart.saveDir = /tmp

  

清單10 struts配置

這樣上傳的檔案就會臨時儲存到你根目錄下的tmp檔案夾中(一般為c:\tmp),如果此檔案夾不存在,Struts 2會自動建立一個。

錯誤處理

上述例子實現的圖片上傳的功能,所以應該阻止使用者上傳非圖片類型的檔案。在Struts 2中如何?這點呢?其實這也很簡單,對上述例子作如下修改即可。

首先修改FileUpload.jsp,在<body>與<s:form>之間加入“<s:fielderror />”,用於在頁面上輸出錯誤資訊。

然後修改struts.xml檔案,將Action fileUpload的定義改為如下所示:

       
 < action name ="fileUpload" class ="tutorial.FileUploadAction" >             < interceptor-ref name ="fileUpload" >                 < param name ="allowedTypes" >                     image/bmp,image/png,image/gif,image/jpeg                </ param >             </ interceptor-ref >             < interceptor-ref name ="defaultStack" />                        < result name ="input" > /FileUpload.jsp </ result >             < result name ="success" > /ShowUpload.jsp </ result >         </ action >

  

清單11 修改後的設定檔

顯而易見,起作用就是fileUpload攔截器的allowTypes參數。另外,配置還引入defaultStack它會幫我們添加驗證等功能,所以在出錯之後會跳轉到名稱為“input”的結果,也即是FileUpload.jsp。

發布運行應用程式,出錯時,頁面如所示:

 
清單12 出錯提示頁面

上面的出錯提示是Struts 2預設的,大多數情況下,我們都需要自訂和國際化這些資訊。通過在全域的國際資源檔中加入“struts.messages.error.content.type.not.allowed=The file you uploaded is not a image”,可以實現以上提及的需求。對此有疑問的朋友可以參考我之前的文章《在Struts 2.0中國際化(i18n)您的應用程式》。

實現之後的出錯頁面如所示:

 
清單13 自訂出錯提示頁面

同樣的做法,你可以使用參數“maximumSize”來限制上傳檔案的大小,它對應的字元資源名為:“struts.messages.error.file.too.large”。

字元資源“struts.messages.error.uploading”用提示一般的上傳出錯資訊。

多檔案上傳

與單檔案上傳相似,Struts 2實現多檔案上傳也很簡單。你可以將多個<s:file />綁定Action的數組或列表。如下例所示。

< s:form action ="doMultipleUploadUsingList" method ="POST" enctype ="multipart/form-data" >     < s:file label ="File (1)" name ="upload" />     < s:file label ="File (2)" name ="upload" />     < s:file label ="FIle (3)" name ="upload" />     < s:submit /> </ s:form >

  

清單14 多檔案上傳JSP程式碼片段

如果你希望綁定到數組,Action的代碼應類似:

 
    private File[] uploads;     private String[] uploadFileNames;     private String[] uploadContentTypes;     public File[] getUpload() { return this .uploads; }      public void setUpload(File[] upload) { this .uploads = upload; }       public String[] getUploadFileName() { return this .uploadFileNames; }      public void setUploadFileName(String[] uploadFileName) { this .uploadFileNames = uploadFileName; }       public String[] getUploadContentType() { return this .uploadContentTypes; }      public void setUploadContentType(String[] uploadContentType) { this .uploadContentTypes = uploadContentType; }

  

清單15 多檔案上傳數組綁定Action程式碼片段

如果你想綁定到列表,則應類似:

     private List < File > uploads = new ArrayList < File > ();     private List < String > uploadFileNames = new ArrayList < String > ();     private List < String > uploadContentTypes = new ArrayList < String > ();     public List < File > getUpload() {         return this .uploads;    }      public void setUpload(List < File > uploads) {         this .uploads = uploads;    }       public List < String > getUploadFileName() {         return this .uploadFileNames;    }      public void setUploadFileName(List < String > uploadFileNames) {         this .uploadFileNames = uploadFileNames;    }       public List < String > getUploadContentType() {         return this .uploadContentTypes;    }      public void setUploadContentType(List < String > contentTypes) {         this .uploadContentTypes = contentTypes;    }

  

清單16 多檔案上傳列表綁定Action程式碼片段

總結

在Struts 2中實現檔案上傳的確是輕而易舉,您要做的只是使用<s:file />與Action的屬性綁定。這又一次有力地證明了Struts 2的簡單易用。

 

本文轉自:http://www.blogjava.net/max/archive/2007/03/21/105124.html

轉:在Struts 2中實現檔案上傳

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.