本文實例講述了java中struts2實作檔案上傳下載功能實作方法。分享給大家供大家參考。具體分析如下:
1.文件上傳
首先是jsp頁面的程式碼
在jsp頁面中定義一個上傳標籤
複製代碼代碼如下:<tr>
<td align="right" bgcolor="#F5F8F9"><b>附件:</b></td>
<td bgcolor="#FFFFFF">
<input type="file" name="upload" />
</td>
<td bgcolor="#FFFFFF"></td>
</tr>
然後是BaseAction中定義的相關屬性其它的就省略了(也可定義在自己的Action,換下訪問修飾符即可)
複製代碼代碼如下:/**
*Action基底類
**/
public class BaseAction extends ActionSupport {
protected List<File> upload;
protected List<String> uploadContentType; //檔案類型
protected List<String> uploadFileName; //檔名
protected String savePath; //儲存路徑
}
然後是Action中的一個上傳方法,程式碼如下:
複製代碼代碼如下:/**
* 8.上傳附件* @param upload
*/
public void uploadAccess(List<File> upload){
try {
if (null != upload) {
for (int i = 0; i < upload.size(); i++) {
String path = getSavePath() + ""+ getUploadFileName().get(i);
System.out.println(path);
item.setAccessory(getUploadFileName().get(i));
FileOutputStream fos = new FileOutputStream(path);
FileInputStream fis = new FileInputStream(getUpload().get(i));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fis.close();
fos.close();
}
}
} catch (Exception e) {
logger.error("上傳附件錯誤。", e);
}
}
接著是我的struts2.xml檔案複製程式碼如下:<action name="itemRDAction_*" method="{1}">
<param name="savePath">e:upload</param>
<interceptor-ref name="defaultStack">
<param name="fileUpload.allowedTypes">
application/octet-stream,image/pjpeg,image/bmp,image/jpg,image/png,image/gif,image/jpeg,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd. ms-excel
</param>
<param name="fileUpload.maximumSize">8000000</param>
</interceptor-ref>
<result name="show_item_rd_upd"> /WEB-INF/jsp/page_item/updItem_rd.jsp</result>
<result name="show_item_rd_list"> /WEB-INF/jsp/page_item/listItem_rd.jsp</result>
<result name="show_item_rd_push"> /WEB-INF/jsp/page_item/pushItem_rd.jsp</result>
</action>
savePath為儲存路徑,fileUpload.allowedTypes 用來限制上傳檔案類型fileUpload.maximumSize 檔案大小限制
2.文件下載
首先是頁面中的下載連結複製程式碼如下:<tr>
<td align="right" bgcolor="#F5F8F9"><b>附件:</b></td>
<td bgcolor="#FFFFFF">
<div>${item.accessory}</div>
<c:if test="${!empty item.accessory}">
<div style="float: left;"><a style="color: black; text-decoration: none;" href="download.action?filename=${item.accessory}">下載</a>< /div>
</c:if>
</td>
<td bgcolor="#FFFFFF"></td>
</tr>
接著是DownloadAction的程式碼:
複製代碼代碼如下:/**
* DownloadAction
*
* @author zhaoxz
*
*/
@Controller("downloadAction")
@Scope("prototype")
public class DownloadAction extends BaseAction {
/**
*
*/
private static final long serialVersionUID = -4278687717124480968L;
private static Logger logger = Logger.getLogger(DownloadAction.class);
private String filename;
private InputStream inputStream;
private String savePath;
private String mimeType;
public InputStream getInputStream() {
try {
String path = getSavePath() + "//"+ new String(filename.getBytes("ISO8859-1"), "utf-8");
System.out.println(path);
mimeType = ServletActionContext.getServletContext().getMimeType(path)+ ";charset=UTF-8";
inputStream = new FileInputStream(path);
String agent = request.getHeader("USER-AGENT");
System.out.println(agent);
if (null != agent) {
if (-1 != agent.indexOf("Firefox")) {// Firefox
mimeType = mimeType.replace("UTF-8", "ISO8859-1");
} else {// IE7+ Chrome
System.out.println("IE,Chrome");
filename = new String(filename.getBytes("ISO8859-1"),"utf-8");
filename = java.net.URLEncoder.encode(filename, "UTF-8");
}
}
} catch (Exception e) {
logger.error("下載檔案資訊出錯。", e);
}
if (null == inputStream) {
System.out.println("getResource error");
}
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
/*************************** get set ******************** **********/
public String getSavePath() {
return this.savePath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
}
然後是它的struts2.xml檔:
複製程式碼如下:<action name="download">
<param name="savePath">E:/upload</param>
<result type="stream">
<param name="contentType">${mimeType}</param>
<param name="contentDisposition">attachment;filename="${filename}"</param>
<param name="inputName">inputStream</param>
</result>
</action>
下載的話注意下編碼格式基本上應該就沒什麼問題了.
上傳過程碰到的問題
1.上傳大檔案就出錯解決方法1
出現的錯誤有如下:
1、2012-02-24 11:06:31,937 ERROR (org.apache.struts2.dispatcher.Dispatcher:512) - Could not find action or result
No result defined for action com.iman.portal.action.QuestionActionImpl and result problemPage - action - file:/E:/myeclipse/workspaces/portal/WebRoot/WEB-INF/classes/struts2/struts-question.xml:51: 55
2、the request was rejected because its size (2973652) exceeds the configured maximum (2097152)
中文意思: 要求被拒絕,因為它的大小(2973652)超過配置的最大值(2097152)、
考慮到使用者體驗,所以必須在上傳附件時,攔截這樣的異常,解決方法如下:
1.所上傳的文件,在上傳過程中都是先存放在快取中的,安全起見,還是在專案的struts.properties文件中,加一個臨時存放路徑,雖然專案中己經設定好伺服器的實體路徑。
複製碼程式碼如下: struts.multipart.saveDir=/temp
2.考慮到後期可能會修改檔案上傳的大小,所以不管是否默認,還是在專案的struts.properties檔案中,加上如下配置:
複製程式碼程式碼如下: <!-- 所允許上傳檔案的大小2M -->
<constant name="struts.multipart.maxSize" value="2097152"/>
3、struts.xml配置
複製程式碼程式碼如下: <!-- 修改問題方法-->
<action name="updateProblem" method="updateProblem">
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="defaultStack" />
<result name="input">/page/question/page/problemPage.jsp</result>
</action>
4.最重要也是最關鍵的一步
fileUpload攔截器只是當檔案上傳到伺服器上之後,才進行的檔案類型和大小判斷。在Action中如果我們什麼操作都不做的話,異常就會展現在使用者的面前,因此想了一個方法,把該異常訊息設定為Action層級的錯誤訊息。即重寫addActionError方法。
複製代碼代碼如下:@Override
public void addActionError(String anErrorMessage) {
// 這裡要先判斷一下,是我們要替換的錯誤,才處理
if (anErrorMessage.startsWith("the request was rejected because its size")) {
Pattern pattern = Pattern.compile("d+");
Matcher m = pattern.matcher(anErrorMessage);
// 匹配一次
m.find();
String s1 =m.group();//上傳的檔案大小
// 再匹配一次
m.find();
String s2 =m.group();//所限制的大小
if(!s1.equals("") && !s2.equals("")){
fileUploadErrorMessage="你上傳的檔案大小(" + Long.valueOf(s1)/1024 +"位元組)超過允許的大小(" + Long.valueOf(s2)/1024/1024 + "M)";
getRequest().setAttribute("fileUploadErrorMessage","檔案太大,超過了允許的大小("+Long.valueOf(s2)/1024/1024+"M),上傳失敗!");
// 將資訊替換掉
super.addActionError(fileUploadErrorMessage);
}
} else {// 否則以原來的方法處理
super.addActionError(anErrorMessage);
}
}
可以,在回傳頁面用<s:fielderror/> <s:fielderror/>,得到addActionError中的錯誤內容。
因為我不打算,在頁面上顯示出來錯誤原因,想彈出一個提示框,所以將資訊放入了request物件中。
而頁面載入時,加瞭如下js驗證:
複製程式碼如下://判斷檔案是否上傳成功
var message="${request.fileUploadErrorMessage}";
if(message!=null && ""!=trim(message) && message!="null"){
self.parent.diag.close();
alert(message);
return;
}
以下是一些參考了解東東:
struts.multipart.maxSize掌控整個專案所上傳檔案的最大的Size
struts.multipart.maxSize和fileUpload攔截器的maximumSize屬性分工不同,總結如下:
1.struts.multipart.maxSize掌控整個專案所上傳檔案的最大的Size。
超過了這個size,後台報錯,程式處理不瞭如此大的文件。 fielderror裡面會有如下的提示:
the request was rejected because its size (16272982) exceeds the configured maximum (9000000)
2.fileUpload攔截器的maximumSize屬性必須小於struts.multipart.maxSize的值。
struts.multipart.maxSize預設2M,當maximumSize大於2M時,必須設定struts.multipart.maxSize的值大於maximumSize。
3.當上傳的檔案大於struts.multipart.maxSize時,系統報錯當上傳的檔案在struts.multipart.maxSize和maximumSize之間時,系統提示:
File too large: file "MSF的概念.ppt" "upload__5133e516_129ce85285f__7ffa_00000005.tmp" 6007104
當上傳的檔案小於maximumSize,上傳成功。
複製程式碼如下:<action name="UploadFile">
<result name="UploadFileResult">/pages/ShowOtherFiles.jsp</result>
<result name="JGBsuccess">/pages/JGBdetail.jsp</result>
<interceptor-ref name="fileUpload">
<param name="savePath">/data</param>
<param name="maximumSize">52428800</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
上傳大檔案就出錯解決辦法2:
問題:上傳大文件報錯誤…
解決:修改struts.xml檔案中的參數如下複製程式碼如下:<constant name="struts.multipart.maxSize" value="55000000"/>
<action name="UploadFile">
<result name="UploadFileResult">/www.VeVB.COm/ ShowOtherFiles.jsp</result>
<result name="JGBsuccess">/pages/JGBdetail.jsp</result>
<interceptor-ref name="fileUpload">
<param name="savePath">/data</param>
<param name="maximumSize">52428800</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
struts.xml檔案中的大小與實際檔案大小的關係:1048576(Bytes) = 1024*1024 = 1M實際檔案大小.
struts.multipart.maxSize掌控整個專案所上傳檔案的最大的Size
struts.multipart.maxSize和fileUpload攔截器的maximumSize屬性分工不同,總結如下:
1.struts.multipart.maxSize掌控整個專案所上傳檔案的最大的Size。超過了這個size,後台報錯,程式處理不瞭如此大的文件。 fielderror裡面會有如下的提示:
the request was rejected because its size (16272982) exceeds the configured maximum (9000000)
2.fileUpload攔截器的maximumSize屬性必須小於struts.multipart.maxSize的值。
struts.multipart.maxSize預設2M,當maximumSize大於2M時,必須設定struts.multipart.maxSize的值大於maximumSize。
3.當上傳的檔案大於struts.multipart.maxSize時,系統報錯當上傳的檔案在struts.multipart.maxSize和maximumSize之間時,系統提示:
File too large: file "MSF的概念.ppt" "upload__5133e516_129ce85285f__7ffa_00000005.tmp" 6007104
當上傳的檔案小於maximumSize,上傳成功。
上傳文件的類型限制
配置fileupload攔截器
struts2的defaultStack中已經含有fileupload攔截器,如果想加入allowedTypes參數,需要從新寫一個defaultstack ,拷貝過來修改一下即可:
複製程式碼如下:<interceptors>
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name=www.VeVB.COm/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedModelDriven"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload">
<param name="allowedTypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="actionMappingParams"/>
<interceptor-ref name="params">
<param name="excludeParams">dojo..*,^struts..*</param>
</interceptor-ref>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
僅修改程式碼中的複製程式碼如下:<interceptor-ref name="fileUpload">
<param name="allowedTypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
攔截器棧在<package>標籤內<action>標籤外配置如上我們如果把它定義成預設攔截器的話就不需要在
<action>標籤中引入,沒有的話需要引入攔截器複製代碼代碼如下:<action>
<result name="input">/error/dbError.jsp</result>
<interceptor-ref name="myDefaultStack"></interceptor-ref>
</action>
檔案上傳類型錯誤action會直接回傳input,所以不需要在action中return "input" ;
還可以在<package>標籤外定義上傳問價你的路徑跟大小:
複製程式碼如下:<constant name="struts.multipart.saveDir" value="/upload/detailed"></constant>
<constant name="struts.multipart.maxSize" value="1024"></constant>
最重要的一點:上傳檔案的表單必須加上:enctype="multipart/form-data" 不加必然報input錯誤。
希望本文所述對大家的Java程式設計有幫助。