轉載於:http://www.cnblogs.com/xiaoluo501395377/archive/2012/10/26/2740882.htmljavascript
在作B/S系統時,一般會涉及到上傳文件和下載文件,在沒接struts2框架以前,咱們都是使用apache下面的commons子項目的FileUpload組件來進行文件的上傳,可是那樣作的話,代碼看起來比較繁瑣,並且不靈活,在學習了struts2後,struts2爲文件上傳下載提供了更好的實現機制,在這裏我分別就單文件上傳和多文件上傳的源代碼進行一下講解,這裏須要導入文件下載上傳的兩個jar文件,一個是commons-fileupload-1.2.2.jar,另外一個是commons-io-2.0.1.jarhtml
struts2單文件上傳:前端
首先是一個jsp文件上傳頁面,這個比較簡單,就是一個表單,裏面有個文件上傳框java
<!--在進行文件上傳時,表單提交方式必定要是post的方式,由於文件上傳時二進制文件可能會很大,還有就是enctype屬性,這個屬性必定要寫成multipart/form-data,
否則就會以二進制文本上傳到服務器端-->
<form action="fileUpload.action" method="post" enctype="multipart/form-data"> username: <input type="text" name="username"><br> file: <input type="file" name="file"><br> <input type="submit" value="submit"> </form>
接下來是FileUploadAction部分代碼,由於struts2對上傳和下載都提供了很好的實習機制,因此在action這段咱們只須要寫不多的代碼就行:jquery
public class FileUploadAction extends ActionSupport { private String username;
//注意,file並非指前端jsp上傳過來的文件自己,而是文件上傳過來存放在臨時文件夾下面的文件 private File file; //提交過來的file的名字 private String fileFileName; //提交過來的file的MIME類型 private String fileContentType; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public File getFile() { return file; } public void setFile(File file) { this.file = file; } public String getFileFileName() { return fileFileName; } public void setFileFileName(String fileFileName) { this.fileFileName = fileFileName; } public String getFileContentType() { return fileContentType; } public void setFileContentType(String fileContentType) { this.fileContentType = fileContentType; } @Override public String execute() throws Exception { String root = ServletActionContext.getServletContext().getRealPath("/upload"); InputStream is = new FileInputStream(file); OutputStream os = new FileOutputStream(new File(root, fileFileName)); System.out.println("fileFileName: " + fileFileName);
// 由於file是存放在臨時文件夾的文件,咱們能夠將其文件名和文件路徑打印出來,看和以前的fileFileName是否相同 System.out.println("file: " + file.getName()); System.out.println("file: " + file.getPath()); byte[] buffer = new byte[500]; int length = 0; while(-1 != (length = is.read(buffer, 0, buffer.length))) { os.write(buffer); } os.close(); is.close(); return SUCCESS; } }
首先咱們要清楚一點,這裏的file並非真正指代jsp上傳過來的文件,當文件上傳過來時,struts2首先會尋找struts.multipart.saveDir(這個是在default.properties裏面有)這個name所指定的存放位置,咱們能夠新建一個struts.properties屬性文件來指定這個臨時文件存放位置,若是沒有指定,那麼文件會存放在tomcat的apache-tomcat-7.0.29\work\Catalina\localhost\目錄下,而後咱們能夠指定文件上傳後的存放位置,經過輸出流將其寫到流裏面就好了,這時咱們就能夠在文件夾裏看到咱們上傳的文件了。apache
文件上傳後咱們還須要將其下載下來,其實struts2的文件下載原理很簡單,就是定義一個輸入流,而後將文件寫到輸入流裏面就行,關鍵配置仍是在struts.xml這個配置文件裏配置:數組
FileDownloadAction代碼以下:瀏覽器
public class FileDownloadAction extends ActionSupport { public InputStream getDownloadFile() { return ServletActionContext.getServletContext().getResourceAsStream("upload/通信錄2012年9月4日.xls"); } @Override public String execute() throws Exception { return SUCCESS; } }
咱們看,這個action只是定義了一個輸入流,而後爲其提供getter方法就行,接下來咱們看看struts.xml的配置文件:tomcat
<action name="fileDownload" class="com.xiaoluo.struts2.FileDownloadAction"> <result name="success" type="stream"> <param name="contentDisposition">attachment;filename="通信錄2012年9月4日.xls"</param> <param name="inputName">downloadFile</param> </result> </action>
struts.xml配置文件有幾個地方咱們要注意,首先是result的類型,之前咱們定義一個action,result那裏咱們基本上都不寫type屬性,由於其默認是請求轉發(dispatcher)的方式,除了這個屬性通常還有redirect(重定向)等這些值,在這裏由於咱們用的是文件下載,因此type必定要定義成stream類型,告訴action這是文件下載的result,result元素裏面通常還有param子元素,這個是用來設定文件下載時的參數,inputName這個屬性就是獲得action中的文件輸入流,名字必定要和action中的輸入流屬性名字相同,而後就是contentDisposition屬性,這個屬性通常用來指定咱們但願經過怎麼樣的方式來處理下載的文件,若是值是attachment,則會彈出一個下載框,讓用戶選擇是否下載,若是不設定這個值,那麼瀏覽器會首先查看本身可否打開下載的文件,若是能,就會直接打開所下載的文件,(這固然不是咱們所須要的),另一個值就是filename這個就是文件在下載時所提示的文件下載名字。在配置完這些信息後,咱們就能過實現文件的下載功能了。服務器
struts2多文件上傳:
其實多文件上傳和單文件上傳原理同樣,單文件上傳過去的是單一的File,多文件上傳過去的就是一個List<File>集合或者是一個File[]數組,首先咱們來看一下前端jsp部分的代碼,這裏我用到了jquery來實現動態的添加文件下載框以及動態的刪除下載框:
<script type="text/javascript" src="script/jquery-1.8.1.js"></script> <script type="text/javascript"> $(function() { $("#button").click(function() { var html = $("<input type='file' name='file'>"); var button = $("<input type='button' name='button' value='刪除'><br>"); $("#body div").append(html).append(button); button.click(function() { html.remove(); button.remove(); }) }) }) </script> </head> <body id="body"> <form action="fileUpload2.action" method="post" enctype="multipart/form-data"> username: <input type="text" name="username"><br> file: <input type="file" name="file"> <input type="button" value="添加" id="button"><br> <div></div> <input type="submit" value="submit"> </form> </body>
file的名字必須都命名成file才行,而後處理多文件上傳的action代碼以下:
public class FileUploadAction2 extends ActionSupport { private String username;
//這裏用List來存放上傳過來的文件,file一樣指的是臨時文件夾中的臨時文件,而不是真正上傳過來的文件 private List<File> file;
//這個List存放的是文件的名字,和List<File>中的文件相對應 private List<String> fileFileName; private List<String> fileContentType; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public List<File> getFile() { return file; } public void setFile(List<File> file) { this.file = file; } public List<String> getFileFileName() { return fileFileName; } public void setFileFileName(List<String> fileFileName) { this.fileFileName = fileFileName; } public List<String> getFileContentType() { return fileContentType; } public void setFileContentType(List<String> fileContentType) { this.fileContentType = fileContentType; } @Override public String execute() throws Exception { String root = ServletActionContext.getServletContext().getRealPath("/upload"); for(int i = 0; i < file.size(); i++) { InputStream is = new FileInputStream(file.get(i)); OutputStream os = new FileOutputStream(new File(root, fileFileName.get(i))); byte[] buffer = new byte[500]; @SuppressWarnings("unused") int length = 0; while(-1 != (length = is.read(buffer, 0, buffer.length))) { os.write(buffer); } os.close(); is.close(); } return SUCCESS; } }
這樣一樣將其寫到一個輸出流裏面,這樣咱們就能夠在文件夾裏看到上傳的多個文件了
接下來的文件下載就和剛纔的文件下載如出一轍,struts.xml也是同樣的,這裏就再也不重複了
總結:總的來講,struts2提供的文件上傳下載機制簡化了咱們不少代碼,咱們能夠在之後的項目中使用該機制,一樣咱們也可使用FileUpload組件來進行文件的上傳,這個都是因我的愛好決定!