在做B/S系統時,通常會涉及到上傳檔案和下載下傳檔案,在沒接struts2架構之前,我們都是使用apache下面的commons子項目的FileUpload元件來進行檔案的上傳,但是那樣做的話,代碼看起來比較繁瑣,而且不靈活,在學習了struts2後,struts2為檔案上傳下載下傳提供了更好的實作機制,在這裡我分别就單檔案上傳和多檔案上傳的源代碼進行一下講解,這裡需要導入檔案下載下傳上傳的兩個jar檔案,一個是commons-fileupload-1.2.2.jar,另一個是commons-io-2.0.1.jar
struts2單檔案上傳:
首先是一個jsp檔案上傳頁面,這個比較簡單,就是一個表單,裡面有個檔案上傳框
原理是就是struts2的FileUploadInterceptor攔截器過濾。
接下來是FileUploadAction部分代碼,因為struts2對上傳和下載下傳都提供了很好的實習機制,是以在action這段我們隻需要寫很少的代碼就行:
Action中檔案屬性的命名規則約定,在struts2内部的的FileUploadInterceptor.class完成的
String[] fileName = multiWrapper.getFileNames(inputName);//得到請求的所有檔案名
if (isNonEmpty(fileName)) {
// get a File object for the uploaded File
File[] files = multiWrapper.getFiles(inputName);
if (files != null && files.length > 0) {
List<File> acceptedFiles = new ArrayList<File>(files.length);
List<String> acceptedContentTypes = new ArrayList<String>(files.length);
List<String> acceptedFileNames = new ArrayList<String>(files.length);
String contentTypeName = inputName + "ContentType";//預設就是input名稱+ContentType
String fileNameName = inputName + "FileName";//預設就是input名稱+FileName
for (int index = 0; index < files.length; index++) {
if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) {
acceptedFiles.add(files[index]);
acceptedContentTypes.add(contentType[index]);
acceptedFileNames.add(fileName[index]);
}
}
if (!acceptedFiles.isEmpty()) {
Map<String, Object> params = ac.getParameters();//添加到parameters中 這樣就可以通過OGNL注入到action了
params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
}
自己寫的例子:
package action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.servlet.ServletContext;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class UploadAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private File file;
private String fileContentType;
private String fileFileName;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
public String getFileContentType() {
return fileContentType;
public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
public String getFileFileName() {
return fileFileName;
public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println("file:"+file);
System.out.println("fileContentType:"+fileContentType);
System.out.println("fileFileName:"+fileFileName);
ServletContext ctx=ServletActionContext.getServletContext();
/*String dir=ctx.getRealPath("/files/"+fileFileName);
new File(dir).getParentFile().mkdir();
FileOutputStream out=new FileOutputStream(dir);*/
String dir=ctx.getRealPath("/files");
new File(dir).mkdir();
FileOutputStream out=new FileOutputStream(dir+"/"+fileFileName);
System.out.println(dir+"/"+fileFileName);
FileInputStream in=new FileInputStream(file);
byte[] buffer=new byte[1024];
int len=0;
while((len=in.read(buffer))!=-1){
out.write(buffer,0,len);
out.close();
in.close();
return super.execute();
首先我們要清楚一點,這裡的file并不是真正指代jsp上傳過來的檔案,當檔案上傳過來時,struts2首先會尋找struts.multipart.saveDir(這個是在default.properties裡面有)這個name所指定的存放位置,我們可以建立一個struts.properties屬性檔案來指定這個臨時檔案存放位置,如果沒有指定,那麼檔案會存放在tomcat的apache-tomcat-7.0.29\work\Catalina\localhost\目錄下,然後我們可以指定檔案上傳後的存放位置,通過輸出流将其寫到流裡面就行了,這時我們就可以在檔案夾裡看到我們上傳的檔案了。
檔案上傳後我們還需要将其下載下傳下來,其實struts2的檔案下載下傳原理很簡單,就是定義一個輸入流,然後将檔案寫到輸入流裡面就行,關鍵配置還是在struts.xml這個配置檔案裡配置:
FileDownloadAction代碼如下:
我們看,這個action隻是定義了一個輸入流,然後為其提供getter方法就行,接下來我們看看struts.xml的配置檔案:
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來實作動态的添加檔案下載下傳框以及動态的删除下載下傳框:
file的名字必須都命名成file才行,然後處理多檔案上傳的action代碼如下:
這樣同樣将其寫到一個輸出流裡面,這樣我們就可以在檔案夾裡看到上傳的多個檔案了
接下來的檔案下載下傳就和剛才的檔案下載下傳一模一樣,struts.xml也是一樣的,這裡就不再重複了
總結:總的來說,struts2提供的檔案上傳下載下傳機制簡化了我們很多代碼,我們可以在以後的項目中使用該機制,同樣我們也可以使用FileUpload元件來進行檔案的上傳,這個都是因個人愛好決定!