文件上傳和文件下載是我們在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/?μí3?μ?÷.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");
|
新聞熱點
疑難解答