檔案上傳和檔案下載是我們在web應用程式中常用的兩個功能,在java中,實現這兩種功能的方式也有很多種,其中struts2就給我們提供了一種算是比較簡單的方式吧,下面我們就一起來看一下,首先我們來看檔案上傳:
檔案上傳
檔案上傳我們首先應該注意的是在上傳頁面的表單,這個表單也是有講究的,由於我們提交表單的資料中有檔案上傳,所以這個表單的所使用的編碼類別型就不能是原來的了,在這裡我們應該使用的編碼方式是multipart/form-data,並且資料提交方式要用post方式,下面我們具體來看一下:
Form.jsp:
<form action="StudentAction!addStu" target="mainFrame" onsubmit="javascript:window.close()" method="post" enctype="multipart/form-data"><table class="ta" width="200px"><td>姓名</td><td><input type="text" name="stu.name" value="${request.stu_info.name }"/></td></tr><tr bgColor="#6fdd0"><td>上傳頭像</td><td><input type="file" name="file" /> </td></tr><tr bgColor="#6fdd0"><td colspan="2"><input type="submit" value="提交" class="buStyle"/> <input type="reset" value="重設" class="buStyle"/></td></tr></table></form>
OK,看完表單以後我們就要來看一下action裡面是怎麼來接收這些資料的,其實也很簡單,直接在action中定義三個變數,這三個變數分別是檔案、檔案名稱,還有檔案類型,如下:
private File file;private String fileFileName;private String fileContentType;
這三個變數的名字是有講究的,不是隨便命名就OK了,其中file這個變數名要和表單中檔案的name要相同,fileFileName這個也是固定的,起名格式就是name+FileName,同樣fileContentType也是如此,命名規則是name+ContentType,只有你按照命名規則來定義變數,struts2才能把檔案上傳相關資訊收集起來。Ok,看完了變數設定,下面我們來看一下怎麼struts2是怎麼把檔案上傳到我們指定的位置的。那我們就先上代碼,讓代碼幫我們來理解:
String root = ServletActionContext.getRequest().getRealPath("/upload");try{InputStream is = new FileInputStream(file);// 建立一個檔案,路徑為root,檔案名稱叫fileFileName//自訂檔案名稱fileFileName="111"+fileFileName.substring(fileFileName.lastIndexOf("."));File destFile = new File(root, fileFileName);// 開始上傳OutputStream os = new FileOutputStream(destFile);byte[] buffer = new byte[50000];int length = 0;// enctype="multipart/form-data"while (-1 != (length = is.read(buffer))) {os.write(buffer, 0, length);}
我們可以看到,就是簡單的幾行代碼,其實並不難,他主要就是利用了IO流來實現的檔案上傳。單檔案上傳實現以後,多檔案上傳實現起來就不難了。
多檔案上傳
與單檔案上傳相似,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 >
如果你希望綁定到數組,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; }
如果你想綁定到列表,則應類似:
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; }
收集好資料之後,檔案上傳步驟就和上面單檔案的一樣了。在這就不重複了。好了,檔案上傳占時先說到這,下一步我們來看一下檔案下載。
檔案下載
Struts 2中對檔案下載做了直接的支援,相比起自己辛辛苦苦的設定種種HTTP頭來說,現在實現檔案下載無疑要簡便的多。說起檔案下載,最直接的方式恐怕是直接寫一個超連結,讓地址等於被下載的檔案,例如:<a href=”file1.zip”> 下載file1.zip</a> ,之後使用者在瀏覽器裡面點擊這個連結,就可以進行下載了。但是它有一些缺陷,例如如果地址是一個圖片,那麼瀏覽器會直接開啟它,而不是顯示儲存檔案的對話方塊。再比如如果檔案名稱是中文的,它會顯示一堆URL編碼過的檔案名稱例如%3457...。而假設你企圖這樣下載檔案:http://localhost:8080/struts2/download/java程式員由笨鳥到菜鳥.doc ,Tomcat會告訴你一個檔案找不到的404錯誤:HTTP Status 404 - /struts2hello/download/ϵͳ˵Ã÷.doc 。 所以在此我們就要用到struts 給我們提供的檔案下載了。下面我們就一起來看一下struts2給我們提供的檔案下載:
其實struts2提供給我們的檔案下載已經非常簡單化了,編寫一個普通的Action就可以了,只需要提供一個返回InputStream流的方法,該輸入資料流代表了被下載檔案的入口,這個方法用來給被下載的資料提供輸入資料流,意思是從這個流讀出來,再寫到瀏覽器那邊供下載。這個方法需要由開發人員自己來編寫,只需要傳回值為InputStream即可 。首先我們來看一下jsp頁面:
<body> <h1>檔案下載</h1> <!-- 下載連結 --> <s:a action="down.action">download</s:a> </body>
頁面很簡單,就一下下載的連結,然後這個網站連結接到我們的action中,下一步我們來看一下我們的action的編寫:
public class DownAction extends ActionSupport { private static final long serialVersionUID = 1L; private String inputPath; public String getInputPath() { return inputPath; } public void setInputPath(String inputPath) { this.inputPath = inputPath; } /* * 下載用的Action應該返回一個InputStream執行個體,該方法對應在result裡的inputName屬性為 * getDownloadFile */ public InputStream getDownloadFile() { return ServletActionContext.getServletContext().getResourceAsStream( "/upload/Struts2.txt"); } public String execute() throws Exception {
return SUCCESS;
}
}
下面我們在來看一下struts.xml的配置:
<action name="down" class="cn.csdn.hr.up.action.DownAction"> <!-- 配置結果類型為stream的結果 --> <result name="success" type="stream"> <!-- 指定被下載檔案的檔案類型 --> <param name="contentType">text/plain </param> <!-- 指定下載檔案的檔案位置 --> <param name="contentDisposition">attachment;filename="Struts2.txt"</param> <param name="inputName">downloadFile</param> </result> </action>
這個action特殊的地方在於result的類型是一個流(stream ),配置stream類型的結果時,因為無需指定實際的顯示的實體資源,所以無需指定location 屬性,只需要指定inputName 屬性,該屬性指向被下載檔案的來源,對應著Action類中的某個屬性,類型為InputStream。下面則列出了和下載有關的一些參數列表:
參數說明
contentType
內容類型,和互連網MIME標準中的規定類型一致,例如text/plain代表純文字,text/xml表示XML,image/gif代表GIF圖片,image/jpeg代表JPG圖片
inputName
下載檔案的來源流,對應著action類中某個類型為Inputstream的屬性名稱,例如取值為inputStream 的屬性需要編寫getInputStream()方法
contentDisposition
檔案下載的處理方式,包括內聯(inline)和附件(attachment)兩種方式,而附件方式會彈出檔案儲存對話方塊,否則瀏覽器會嘗試直接顯示檔案。取值為:attachment;filename="struts2.txt" ,表示檔案下載的時候儲存的名字應為struts2.txt 。如果直接寫filename="struts2.txt" ,那麼預設情況是代表inline ,瀏覽器會嘗試自動開啟它,等價於這樣的寫法:inline; filename="struts2.txt"
bufferSize
下載緩衝區的大小
在這裡面,contentType 屬性和contentDisposition 分別對應著HTTP響應中的頭Content-Type 和Content-disposition 頭
當然,在很多的時候我們一般都不是把檔案名稱寫死在xml配置當中的,我們一般會在action中定義一個變數downfilename,儲存這個檔案名稱,然後再xml配置:
<param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
我們經常在中文下載中,出現檔案名稱亂碼的問題,這個問題是很多人都常見的,具體的很好的解決方案也沒有,但我以前用的時候嘗試著給他重新編碼,這樣可以解決大部分時候的中文下載亂碼問題,但有時候也不行的。具體重新編碼就是:
downFileName = new String(downFileName.getBytes(), "ISO8859-1");
好了,struts2檔案上傳和下載就簡單介紹到這,文章中有什麼不對或者錯誤的地方,歡迎大家指正。