Struts2攔截器之FileUploadInterceptor

 1、它能作什麼?前端

 藉助於這個攔截器咱們能夠實現文件的上傳和下載功能。java

 理論部分:apache

struts2的文件上傳下載功能也要依賴於Apache commons-fileupload和Apache commons-io兩個開源項目,要使用上傳功能就須要把它們引入到classpath中。數組

好比考慮上傳文件,幾個關鍵點就是能夠傳什麼類型的文件?能夠傳多大的文件?傳過來之後放哪兒?叫什麼名字?瀏覽器

當文件上傳過來的時候是放在一個臨時目錄裏的,咱們在Action中持有一個成員屬性File,這個File指向的就是服務器存放上傳文件的臨時目錄中的實際文件(臨時目錄中的文件不會長久保存)服務器

這個是default.properties中默認的一些屬性,不配置臨時目錄的話默認就是用javax.servlet.context.tempdirapp

# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
struts.multipart.maxSize=2097152

能夠在配置文件中使用配置常量,這個配置的常量是全局的,意思就是struts.multipart.saveDir表示全部上傳的文件都臨時保存在這個目錄中,而struts.multipart.maxSize指的是整個項目的上傳文件的最大的size不能超過多少。jsp

而下面這個是在action下設置的,針對的是單個的Action級別的:ide

allowedExtensionsSet 容許的文件類型擴展名,基於擴展名檢查並非特別靠譜post

allowedTypesSet 容許的文件類型

maximumSize 容許的文件大小,這個zhide是一次上傳的文件大小的上限

2、如何作?

1. 單文件上傳:

首先來一個最簡單的用法,即一次上傳一個文件,參數都使用默認值。

只須要寫一個前端:

  <form action="uploadAction" method="post" enctype="multipart/form-data">
      <input type="file" name="file"/><br/>
      <input type="submit" value="上傳" />
  </form>

  而後定義Action:

 1 public class UploadAction extends ActionSupport {
 2 
 3     private File file; //與表單file控件的name一致,指向了服務器臨時目錄中的上傳文件
 4     private String fileContentType; //File變量的名+ContentType,表示文件的MIME類型
 5     private String fileFileName; //File變量的名+FileName,表示文件上傳以前的名稱
 6 
 7     @Override
 8     public String execute() throws Exception {
 9         
10         System.out.println(file+" "+fileContentType+" "+fileFileName);
11         
12         //do something...
13         
14         return SUCCESS;
15     }
16 
17     public File getFile() {
18         return file;
19     }
20 
21     public void setFile(File file) {
22         this.file = file;
23     }
24 
25     public String getFileContentType() {
26         return fileContentType;
27     }
28 
29     public void setFileContentType(String fileContentType) {
30         this.fileContentType = fileContentType;
31     }
32 
33     public String getFileFileName() {
34         return fileFileName;
35     }
36 
37     public void setFileFileName(String fileFileName) {
38         this.fileFileName = fileFileName;
39     }
40 
41 }

 Action中的三個變量:

File file : 對於單文件上傳類型,這個文件的名字必須是File類型的而且變量的名字要和前端表單的文件控件的name屬性一致,會給這個變量賦值指向處於服務器上傳文件臨時目錄中的那個文件。

fileContentType :文件的MIME類型,好比image/jpeg,application/octet-stream之類的。

fileFileName : 文件名,文件在上傳以前在客戶端的磁盤上存在就必然有一個名字,這裏就是那個名字。

總結一下單文件上傳:

1.表單的enctype="multipart/form-data"屬性。

2.Action的三個成員變量file(文件自己),fileContentType(文件MIME類型),fileFileName(文件名)。

2. 多文件上傳

  <form action="uploadAction" method="post" enctype="multipart/form-data">
      <input type="file" name="file"/><br/>
      <input type="file" name="file"/><br/>
      <input type="submit" value="上傳" />
  </form>

 Action:

 1 public class UploadAction extends ActionSupport {
 2 
 3     private File file[]; // 與表單file控件的name一致,指向了服務器臨時目錄中的上傳文件
 4     private String fileContentType[]; // File變量的名+ContentType,表示文件的MIME類型
 5     private String fileFileName[]; // File變量的名+FileName,表示文件上傳以前的名稱
 6 
 7     @Override
 8     public String execute() throws Exception {
 9 
10         for(int i=0;i<file.length;i++){
11             System.out.println(file[i]+" "+fileContentType[i]+" "+fileFileName[i]);
12         }
13         
14         // do something...
15 
16         return SUCCESS;
17     }
18 
19     public File[] getFile() {
20         return file;
21     }
22 
23     public void setFile(File[] file) {
24         this.file = file;
25     }
26 
27     public String[] getFileContentType() {
28         return fileContentType;
29     }
30 
31     public void setFileContentType(String[] fileContentType) {
32         this.fileContentType = fileContentType;
33     }
34 
35     public String[] getFileFileName() {
36         return fileFileName;
37     }
38 
39     public void setFileFileName(String[] fileFileName) {
40         this.fileFileName = fileFileName;
41     }
42 
43 }

 或者:

 1 public class UploadAction extends ActionSupport {
 2 
 3     private List<File> file; // 與表單file控件的name一致,指向了服務器臨時目錄中的上傳文件
 4     private List<String> fileContentType; // File變量的名+ContentType,表示文件的MIME類型
 5     private List<String> fileFileName; // File變量的名+FileName,表示文件上傳以前的名稱
 6 
 7     @Override
 8     public String execute() throws Exception {
 9 
10         for (int i = 0; i < file.size(); i++) {
11             System.out.println(file.get(i) + " " + fileContentType.get(i) + " "
12                     + fileFileName.get(i));
13         }
14 
15         // do something...
16 
17         return SUCCESS;
18     }
19 
20     public List<File> getFile() {
21         return file;
22     }
23 
24     public void setFile(List<File> file) {
25         this.file = file;
26     }
27 
28     public List<String> getFileContentType() {
29         return fileContentType;
30     }
31 
32     public void setFileContentType(List<String> fileContentType) {
33         this.fileContentType = fileContentType;
34     }
35 
36     public List<String> getFileFileName() {
37         return fileFileName;
38     }
39 
40     public void setFileFileName(List<String> fileFileName) {
41         this.fileFileName = fileFileName;
42     }
43 
44 }

 多文件上傳的要點就是在單文件上傳的基礎上前端多個名字相同的表單文件域,Action接收的地方改爲File[]數組或者List<File>集合均可以。

3. 文件下載

 配置文件:

<?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="default" namespace="/" extends="struts-default" >
        <action name="downloadAction" class="struts_practice_001.DownloadAction">
            <!-- 要將結果類型設置爲stream -->
            <result type="stream">
                <!-- inputName跟Action中的輸入流的名字要相同 -->
                <param name="inputName">file</param>
                <!-- contentDisposition的attachment表示讓瀏覽器的默認行爲是保存文件,而filename是保存文件的時候的默認名字 -->
                <param name="contentDisposition">attachment;filename="psd.jpg"</param>
            </result>
        </action>
    </package>
</struts>

 Action:

 1 public class DownloadAction extends ActionSupport {
 2 
 3     private InputStream file; //將要下載的文件讀到這個輸入流中
 4     
 5     @Override
 6     public String execute() throws Exception {
 7         file=ServletActionContext.getServletContext().getResourceAsStream("psb.jpg");
 8         return SUCCESS;
 9     }
10 
11     public InputStream getFile() {
12         return file;
13     }
14 
15     public void setFile(InputStream file) {
16         this.file = file;
17     }
18     
19 }

 文件下載的關鍵點:

1. Action中有一個InputStream,裏面是要被下載的文件的流。

2.配置文件中配置一個爲stream類型的結果,傳入兩個參數:inputName跟Action的InputStream名字保持一致,contentDisposition是給瀏覽器看的提示。

4.配置參數詳解

<struts>
    <!-- 文件上傳到服務器的臨時目錄 -->
    <constant name="struts.multipart.saveDir" value="/tempUpload"></constant>
    <!-- 容許的文件最大尺寸(全局) -->
    <constant name="struts.multipart.maxSize" value="1024000000"></constant>

    <package name="default" namespace="/" extends="struts-default" >
        <action name="uploadAction" class="struts_practice_001.UploadAction">
            <result>/success.jsp</result>
            <interceptor-ref name="fileUpload">
                <!-- 容許的MIME類型 -->
                <param name="allowedTypes">image/bmp,image/png,image/gif,image/jpeg</param>
                <!-- 容許上傳文件的最大尺寸 -->
                <param name="maximumSize">1024000</param>
            </interceptor-ref>
            <!-- 必定要寫在後面 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
        </action>
    </package>
</struts>

 這裏有一點關於參數上的疑問,就是<constant name="struts.multipart.saveDir" value="/tempUpload" />我這樣寫的話這個目錄究竟保存到了哪裏呢?看別的博客上說的是

 發現個人也是保存到了E盤上,可是這種說法很沒有是根本沒有說服力,設想一下若是讓咱們來設計的話,確定要優先保存到剩餘可用空間最大的分區上啦。

若是路徑沒有以/開頭的話就是保存到user.dir。

參考資料:Struts2中的struts.multipart.saveDir的配置

 3、原理是啥?

 

 。。。。好長,之後閒下來再慢慢分析源碼吧。。。

 (沒錯,就這麼太監了.....我發現寫東西是件很奇妙的事情,有的時候連着寫好幾個小時感受很爽,有的時候寫不到十分鐘就感受頭和蛋一塊兒疼明明寫不出來還硬要使勁擠牙膏....o(╯□╰)o)

相關文章
相關標籤/搜索