在做B/S系統時,通常會觸及到上傳文件和下載文件,在沒接struts2框架之前,我們都是使用apache下面的commons子項目的FileUpload組件來進行文件的上傳,但是那樣做的話,代碼看起來比較繁瑣,而且不靈活,在學習了struts2后,struts2為文件上傳下載提供了更好的實現機制,在這里我分別就單文件上傳和多文件上傳的實現進行1下講授,這里
我們使用的struts2 web項目所導入的jar包中的**commons-fileupload⑴.3.1.jar
commons-io⑵.2.jar**是struts2實現上傳下載所使用的類庫
jsp頁面表單的書寫格式
<form name="myForm" enctype="multipart/form-data">
<input type="file" name="myDoc" value="Browse ..." />
<input type="submit" />
</form>
public void setMyDoc(File myDoc)
public void setMyDocContentType(String contentType)
public void setMyDocFileName(String filename)
public File getMyDoc()
public String getMyDocContentType()
public String getMyDocFileName()
首先是1個jsp文件上傳頁面,這個比較簡單,就是1個表單,里面有個文件上傳框
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>Insert title here</title>
</head>
<body>
<!--在進行文件上傳時,表單提交方式1定要是post的方式,由于文件上傳時2進制文件可能會很大,還有就是enctype屬性,這個屬性1定要寫成multipart/form-data,
不然就會以2進制文本上傳到服務器端-->
<form action="upload" method="post" enctype="multipart/form-data">
上傳文件:<input name="photo" type="file"><br>
<input type="submit">
</form>
</body>
</html>
接下來是FileUploadAction部份代碼,由于struts2對上傳和下載都提供了很好的實習機制,所以在action這段我們只需要寫很少的代碼就行:
FileUploadAction.java
package com.lgh.struts2.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import sun.nio.ch.IOUtil;
public class FileUploadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private File photo;
private String photoContentType;
private String photoFileName;
@Override
public String execute() throws Exception {
InputStream is = new FileInputStream(photo);
String path = ServletActionContext.getServletContext().getRealPath("/upload");
String ext = photoFileName.substring(photoFileName.lastIndexOf(".")+1);
System.out.println(ext);
String filePath = path+"/"+UUID.randomUUID()+"."+ext;
OutputStream os = new FileOutputStream(filePath);
System.out.println(path);
IOUtils.copy(is, os);
os.close();
is.close();
return super.execute();
}
public File getPhoto() {
return photo;
}
public void setPhoto(File photo) {
this.photo = photo;
}
public String getPhotoContentType() {
return photoContentType;
}
public void setPhotoContentType(String photoContentType) {
this.photoContentType = photoContentType;
}
public String getPhotoFileName() {
return photoFileName;
}
public void setPhotoFileName(String photoFileName) {
this.photoFileName = photoFileName;
}
}
上傳成功的頁面
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
</body>
</html>
action配置
<action name="upload*" class="com.lgh.struts2.action.FileUpload{1}Action"
method="execute">
<result name="success">/upload_sucess.jsp</result>
</action>
測試
提交落后入上傳文件夾中:
當通過1個表單上傳多個文件, 文件用數組來表示.
給定:
<form name="myForm" enctype="multipart/form-data">
<input type="file" name="myDoc" value="Browse File A ..." />
<input type="file" name="myDoc" value="Browse File B ..." />
<input type="file" name="myDoc" value="Browse File C ..." />
<input type="submit" />
</form>
Action 類定義了文件處理方法,這些方法接收數組參數.
public void setMyDoc(File[] myDocs)
public void setMyDocContentType(String[] contentTypes)
public void setMyDocFileName(String[] fileNames)
通過迭代數組來處理多個文件上傳.
fileuploadMuti.jsp
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>Insert title here</title>
</head>
<body>
<form action="uploadMuti" method="post" enctype="multipart/form-data">
上傳文件:<input name="photo" type="file"><br>
上傳文件:<input name="photo" type="file"><br>
<input type="submit">
</form>
</body>
</html>
FileUploadMutiAction.java
package com.lgh.struts2.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import sun.nio.ch.IOUtil;
public class FileUploadMutiAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private File[] photo;
private String[] photoContentType;
private String[] photoFileName;
@Override
public String execute() throws Exception {
for (int i = 0; i < photo.length; i++) {
InputStream is = new FileInputStream(photo[i]);
String path = ServletActionContext.getServletContext().getRealPath("/upload");
String ext = photoFileName[i].substring(photoFileName[i].lastIndexOf(".")+1);
System.out.println(ext);
String filePath = path+"/"+UUID.randomUUID()+"."+ext;
OutputStream os = new FileOutputStream(filePath);
System.out.println(path);
IOUtils.copy(is, os);
os.close();
is.close();
}
return super.execute();
}
public File[] getPhoto() {
return photo;
}
public void setPhoto(File[] photo) {
this.photo = photo;
}
public String[] getPhotoContentType() {
return photoContentType;
}
public void setPhotoContentType(String[] photoContentType) {
this.photoContentType = photoContentType;
}
public String[] getPhotoFileName() {
return photoFileName;
}
public void setPhotoFileName(String[] photoFileName) {
this.photoFileName = photoFileName;
}
}
action配置:
<action name="upload*" class="com.lgh.struts2.action.FileUpload{1}Action"
method="execute">
<result name="success">/upload_sucess.jsp</result>
</action>
測試:
提交后
屬性 默許值
struts.multipart.parser 使用Commons FileUpload 框架
struts.multipart.saveDir 容器定義的javax.servlet.context.tempdir
設置上傳文件的最大值
struts.multipart.maxSize 大約2M
文件上傳后我們還需要將其下載下來,其實struts2的文件下載原理很簡單,就是定義1個輸入流,然后將文件寫到輸入流里面就行,關鍵配置還是在struts.xml這個配置文件里配置以下參數:
contentType - 告知閱讀器的流的 mime-type (默許 = text/plain).
contentLength - 按字節計算的流長度(閱讀器顯示進度條).
contentDisposition -內容的 disposition 頭值來指定文件的名稱 (默許 = inline, 值通常是 attachment;filename=”document.pdf”.
inputName - the name of the InputStream property from the chained action (默許 = inputStream).
bufferSize - 從輸入往輸出拷貝時緩存的大小 (默許 = 1024).
allowCaching -如果設置為 ‘false’ 將設置頭 ‘Pragma’ 和 ‘Cache-Control’為’no-cahce’, 并禁止客戶端緩存該內容. (默許= true)
contentCharSet -如果設置為字符串, ‘;charset=value’ 將添加到 content-type 頭. 如果為1個表達式, 將使用計算的結果. 如果沒有設置, 將不添加字符編碼到頭
這些參數通過提供與參數名字相同的 getter 方法來設置到你的 Action. 例如, 你可以提供1個 getContentType() 方法來覆蓋當前action的參數.
準備的文件:
文件下載不需要jsp頁面,我們先配置action,這類方式是把下載文件寫死的方式,不可用任意下載:
<action name="download" class="com.lgh.struts2.action.FileDownloadAction"
method="execute">
<result name="success" type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">is</param>
<param name="contentDisposition">attachment;filename="123.jpg"</param>
<param name="bufferSize">1024</param>
</result>
</action>
action類:
FileDownloadAction.java
package com.lgh.struts2.action;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileDownloadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
public InputStream getIs() throws FileNotFoundException{
//文件下載時我們需要1個輸入流來讀取文件,其他的輸出struts2會幫我們創建
return new FileInputStream(ServletActionContext.
getServletContext().getRealPath("/download")+"/123.jpg");
}
}
測試:
經測試下載成功
有時候我們的下載其實不固定格式,比如txt和jpg是兩種不同的格式,123.txt和456.txt下載文件的名字也不相同,這時候我們的struts2.xml中的action配置就不能寫死了,我們需要使它能根據傳遞過來的文件名不同動態的生成1些配置參數的值:
比如:通過OGNL表達式從文件下載action類中通過get方法得到值
<action name="downloadX" class="com.lgh.struts2.action.FileDownloadXAction"
method="execute">
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="inputName">is</param>
<param name="contentDisposition">attachment;filename="${f}"</param>
<param name="bufferSize">1024</param>
</result>
</action>
這時候我們就要在相應的action類中創建get方法了
FileDownloadXAction.java
package com.lgh.struts2.action;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileDownloadXAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String f;
private String contentType;
public InputStream getIs() throws FileNotFoundException{
System.out.println(ServletActionContext.getServletContext().getMimeType(f));
return new FileInputStream(ServletActionContext.
getServletContext().getRealPath("/download")+"/"+f);
}
public String getF() throws UnsupportedEncodingException {
return f;
}
public void setF(String f) {
/*
* 在 tomcat7 中從get要求獲得參數是若包括中文,
* 則會發現中文亂碼現象
* 由于閱讀器傳送來的數據是以utf⑻編碼的,在服務器tomcat則以iso⑻859⑴解碼
* 產生了亂碼,下面代碼可以解決該問題
* new String(f.getBytes("ISO⑻859⑴"),"UTF⑻");
* */
this.f = f;
}
public String getContentType() {
System.out.println(f);
System.out.println(ServletActionContext.getServletContext().getMimeType(f));
return ServletActionContext.getServletContext().getMimeType(f);
}
}
測試
下載文件名非中文的
成功沒有問題
下載中文名字文件
火狐閱讀器:
谷歌閱讀器:
我們看到在下載中文的文件時,文件名都出現了毛病
這是由于:閱讀器在響應頭中不允許中文存在 我們下載時必須content-disposition頭中設置1些下載信息這時候如果我們要下載的文件包括中文,那末我們就必須進行編碼
修改getF()方法:
public String getF() throws UnsupportedEncodingException {
/*
* 閱讀器在響應頭中不允許中文存在
* 我們下載時必須在content-disposition頭中設置1些下載信息
* 這時候如果我們要下載的文件包括中文,那末我們就必須進行編碼
*設置 URLEncoder.encode(name, "utf⑻") 對ie 谷歌 已可以了,
*但是對火狐依然有1些問題
*;filename*=utf-8''"+ URLEncoder.encode(name, "utf-8")
*用于就解決火狐閱讀器的問題
*我們在struts2.xml通過配置的方式也能夠到達以下功能
*
*/
/*
* 這時候我們不使用struts2框架下載時所需要設置的響應頭
* response.setHeader("content-disposition", "attachment;filename=\""+
URLEncoder.encode(name, "utf⑻")+"\";filename*=utf⑻''"+
URLEncoder.encode(name, "utf⑻"));
* */
return URLEncoder.encode(f, "utf⑻");
}
測試:
火狐閱讀器測試:
解決
但是對火狐依然有1些問題
不使用框架則以下代碼 用于就解決火狐閱讀器的問題
;filename*=utf⑻””+ URLEncoder.encode(name, “utf⑻”)
我們在struts2.xml通過配置的方式也能夠到達以下功能
這時候問題解決了:
總的來講,struts2提供的文件上傳下載機制簡化了我們很多代碼,我們可以在以后的項目中使用該機制,一樣我們也能夠使用FileUpload組件來進行文件的上傳,這個都是因個人愛好決定!