struts2 用iframe 作個無刷新上傳文件例子(一)

用Iframe來實現無刷新文件上傳的注意點javascript

1. 頁面須要放一個iframe,並隱藏,而後讓上傳頁面表單的target指定到這個iframecss

2. struts2裏面,中文文件編碼處理,能夠在配置文件,也能夠在action取上傳文件名字的地方,看下面代碼。html

3. 上傳完成後,仍是提交返回到上傳頁面,可是後臺上傳成功的提示信息回傳時,在js 裏面,都必須用parent.xxx的方式,才能訪問到iframe外面的變量和js方法,有點嵌套的意思,比較搞。java

4. 上傳頁面能夠再放一個form,用來下載用。web

5. struts2通常出錯或者取不到值,都是對valueStack和ognl 理解不許確致使的,#號訪問valuestack中非root節點的值,不用#訪問的是action裏面屬性的值,由於action默認是這個valuestack的root節點。ajax

6. struts2 action要取得屬性值,前臺form必須提交過去,就算沒用到,就用隱藏域傳,不然後臺取回報空指針。多文件上傳下載例子裏有實例。spring

7. 無刷新上傳,仍是不要用iframe,太麻煩。尤爲是js訪問iframe外面的方法和變量,或者提交表單,所有要加parent
apache

上代碼json

上傳action,BaseAction其實沒啥,只是提煉了些公用方法,也是直接繼承ActionSupport瀏覽器

package com.hello.web.upAndDownload;

import java.io.File;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hello.util.CommonConstants;
import com.hello.util.FileUtil;
import com.hello.web.BaseAction;
import com.opensymphony.xwork2.ActionContext;
/**
 * 單文件上傳Action
 * */
public class FileUploadAction extends BaseAction {
    private static final long serialVersionUID = 3458871754829140760L;
    private Logger logger = LoggerFactory.getLogger(FileUploadAction.class);
    
    
    private File upload;//頁面上傳文件欄位名
    private String uploadContentType;//文件類型  struts2框架使用,用於判斷是否包含不支持的上傳類型
    private String uploadFileName;//文件名稱
    
    private String saveFileName;//文件轉存後的名字
    
    /**跳轉到上傳界面*/
    public String goUploadPage(){
        logger.debug("跳轉到上傳界面");
        return "uploadPage";
    }
    
    /**
     * 執行文件上傳
     * */
    public String uploadFile(){
        logger.debug("上傳文件名稱:"+uploadFileName);
        logger.debug("上傳文件類型:"+uploadContentType);
        try
        {
            String fileName = FileUtil.generDateStrFilename(uploadFileName);
            HttpServletRequest request = ServletActionContext.getRequest();
            String contextPath = request.getContextPath();//獲取應用上下文路徑
            String destPath = ServletActionContext.getServletContext().getRealPath("/"+CommonConstants.uploadFilePath);
            //logger.debug("保存路徑:"+destPath);
            File destFile = new File(destPath+File.separator+fileName);
            //拷貝文件
            FileUtil.copyFile(upload, destFile);
            //將文件路徑返回到頁面,以供顯示
            //<s:property value="#request.saveFileName"/>方式訪問
            request.setAttribute("realFilePathName", contextPath+"/"+CommonConstants.uploadFilePath+"/"+fileName);
            //文件重名後的名字
            this.setSaveFileName(fileName);
        }catch(Exception e){
            logger.error(uploadFileName+"文件上傳出錯:",e);
        }
        return SUCCESS;
    }
    
    /**
     * 無刷新
     * */
    public String iframeUpload(){
        logger.debug("上傳文件名稱:"+uploadFileName);
        logger.debug("上傳文件類型:"+uploadContentType);
        try
        {
            String fileName = FileUtil.generDateStrFilename(uploadFileName);
            HttpServletRequest request = ServletActionContext.getRequest();
            String contextPath = request.getContextPath();//獲取應用上下文路徑
            String destPath = ServletActionContext.getServletContext().getRealPath("/"+CommonConstants.uploadFilePath);
            //logger.debug("保存路徑:"+destPath);
            File destFile = new File(destPath+File.separator+fileName);
            //拷貝文件
            FileUtil.copyFile(upload, destFile);
            //將文件路徑返回到頁面,以供顯示
            request.setAttribute("realFilePathName", contextPath+"/"+CommonConstants.uploadFilePath+"/"+fileName);
            //文件重名後的名字
            this.setSaveFileName(fileName);
            ActionContext.getContext().put("message", "上傳成功!");
        }catch(Exception e){
            logger.error(uploadFileName+"文件上傳出錯:",e);
        }
        return SUCCESS;
    }
    /**跳轉到上傳界面*/
    public String goIframeUploadPage(){
        logger.debug("跳轉到上傳界面");
        return "iframeUpload";
    }
    
    public File getUpload() {
        return upload;
    }
    public void setUpload(File upload) {
        this.upload = upload;
    }
    public String getUploadContentType() {
        return uploadContentType;
    }
    public void setUploadContentType(String uploadContentType) {
        this.uploadContentType = uploadContentType;
    }
    public String getUploadFileName() {
        return uploadFileName;
    }
    public void setUploadFileName(String uploadFileName) {
        this.uploadFileName = uploadFileName;
    }

    public String getSaveFileName() {
        return saveFileName;
    }

    public void setSaveFileName(String saveFileName) {
        this.saveFileName = saveFileName;
    }
}

下載Action

package com.hello.web.upAndDownload;

import java.io.InputStream;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hello.util.CommonConstants;
import com.hello.web.BaseAction;

/**
 * 文件下載
 * 必須用表單提交,且方法爲POST,才能將隱藏域的值傳進來
 * jsp裏面有fileName,則action裏面使用setFileName方法對應,其餘變量相似
 * jsp裏面取${downloadFileName},至關於調用action裏面的getDownloadFileName方法
 * 
 * */
public class FileDownLoadAction extends BaseAction {
    private static final long serialVersionUID = -929993646660508444L;
    private Logger logger = LoggerFactory.getLogger(FileDownLoadAction.class);
    //下載顯示的文件名
    private String downloadFileName;
    private String realFileName;

    /**
     * 執行下載
     * */
    public String download(){
        logger.debug("下載的文件顯示名:"+downloadFileName);
        logger.debug("下載的文件實際名:"+realFileName);
        
        HttpServletRequest request = ServletActionContext.getRequest();
        logger.debug("從隱藏域裏面取得的值:"+request.getParameter("realFileName"));
        
        return SUCCESS;
    }
    
    public InputStream getInputStream() {
        logger.debug("下載的文件顯示名:"+downloadFileName);
        logger.debug("下載的文件實際名:"+realFileName);
        //InputStream in = ServletActionContext.getServletContext().getResourceAsStream("/" +CommonConstants.uploadFilePath+"/"+ downloadFileName);
        InputStream in = ServletActionContext.getServletContext().getResourceAsStream("/" +CommonConstants.uploadFilePath+"/"+ realFileName);
        if(in==null){
            logger.debug("檢查action中文件下載路徑是否正確!");
        }
        return in;
    }
    
    public void setFileName(String fileName) {
        this.downloadFileName = fileName;
    }

    public String getDownloadFileName() {
        String finalFileName = downloadFileName;
        try {
            // 解決文件名稱包含中文
            HttpServletRequest request = ServletActionContext.getRequest();
            String userAgent = request.getHeader("USER-AGENT");

            if (StringUtils.contains(userAgent, "MSIE")) {// IE瀏覽器
                finalFileName = URLEncoder.encode(downloadFileName, "UTF8");
            } else if (StringUtils.contains(userAgent, "Mozilla")) {// google,火狐瀏覽器
                finalFileName = new String(downloadFileName.getBytes(), "ISO8859-1");
            } else {
                finalFileName = URLEncoder.encode(downloadFileName, "UTF8");// 其餘瀏覽器
            }
        } catch (Exception e) {
            logger.error("下載時,文件名稱轉碼出錯:", e);
        }
        return finalFileName;
    }

    public String getRealFileName() {
        logger.debug("調用 getRealFileName 方法:"+realFileName);
        return realFileName;
    }

    public void setRealFileName(String realFileName) {
        logger.debug("調用 setRealFileName 方法:"+realFileName);
        this.realFileName = realFileName;
    }
}

jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>使用Iframe實現無刷新文件上傳</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
    <style type="text/css">
        body
        {
            line-height: 1.6em;
            font-size: 12px;
        }
        .errorMessage ul
        {
            font-size: 12px;
            font-colr: red;
            backgroundColor:red;
        }
    </style>
    <script type="text/javascript">
        var showName;
        var realName;
        function uploadfile(){
            var ff = document.getElementsByName("upload");
            if(ff[0].value==''|| ff[0].value==null){
                alert('請至少選擇文件!');
            }else{
                document.fileUpload.submit();
            }
        }
        function download(){
            parent.document.getElementById("fileName").value=parent.showName;
            //alert(parent.document.getElementById("fileName").value);
            parent.document.getElementById("realFileName").value=parent.realName;
            parent.document.downloadForm.action="<%= request.getContextPath()%>/file/fileDownload!download.htm";
            parent.document.downloadForm.submit();
        } 
        function show(){
            var msg = '<s:property value="#message"/>';
            parent.showName = '<s:property value="uploadFileName"/>';
            //var realFilePathName = '<s:property value="#request.realFilePathName"/>';//帶路徑的
            parent.realName='<s:property value="saveFileName"/>';//不帶路徑的真實文件名
            parent.document.getElementById("msg").innerHTML = msg;
            parent.document.getElementById("showFileName").innerHTML = "<a href=\"javascript:download();\">"+parent.showName+"</a>";
        }
    </script>
  </head>
  
  <body onload="show();">
    <s:form action ="iframeFileUpload" name="fileUpload" method ="POST" enctype ="multipart/form-data" namespace="/file" theme="simple" target="hidden_frame">   
        <s:actionerror/>
        <s:fielderror />
        <!-- FF和IE瀏覽器顯示的上傳界面不同 --> 
                    請選擇文件:<s:file name ="upload"/><br/>
       (只支持上傳JPG,PNG,GIF,TXT文件)<br/>
        <input type="button" name="btnUpload" value="上傳" onclick="javascript:uploadfile();"/><br/>
           ---------------------------------------------------------------------<br/>
           <span id="msg"></span><br/>
           <span id="showFileName"></span><br/>
           <s:property value="#message"/>
           <s:if test="%{uploadFileName!=null}">
               <s:if test="%{uploadFileName.lastIndexOf(\"txt\")>0}"></s:if>
            <s:else>
                <img  src="<s:property value="#request.realFilePathName"/>"/><br/>
            </s:else>
            <a href="javascript:download();"><s:property value="uploadFileName"/></a><br/>
            
           </s:if>
           <iframe name='hidden_frame' id="hidden_frame" style="display:none;"></iframe>
       </s:form>   
       <form action="<%= request.getContextPath()%>/file/fileDownload!download.htm" name="downloadForm" method="post">
           <input type="hidden" name="fileName" id="fileName"/>
        <input type="hidden" name="realFileName" id="realFileName"/>
       </form>
    <a href="<s:url action="index" method="index" namespace="/"/>">返回首頁</a><br>
  </body>
</html>

配置文件

struts.xml主文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>    
    <!-- struts2常量配置 -->
    <constant name="struts.objectFactory" value="spring" />
    <constant name="struts.objectFactory.spring.useClassCache" value="true" />
    <!-- 國際化配置 -->
    <constant name="struts.locale" value="zh_CN" />
    <constant name="struts.i18n.encoding" value="UTF-8" />
    <constant name="struts.custom.i18n.resources" value="resource.messages,resource.exceptions" />
    <constant name="struts.action.extension" value="htm" />
    <constant name="struts.ui.theme" value="simple" />
    <!-- 部署時修改成false -->
    <constant name="struts.devMode" value="true" />
    <!-- 該屬性指定處理 MIME-type multipart/form-data文件上傳 --> 
    <constant name="struts.multipart.saveDir" value="/tmp"/>
    <!-- <constant name="struts.multipart.paeser" value="cos"/> -->
    <!-- 單位字節Byte 默認2M-->
    <constant name="struts.multipart.maxSize" value="2097152" />  
    <package name="my-default" extends="struts-default">
        <result-types>
            <!-- 配置Json返回類型 -->
            <result-type name="json" class="org.apache.struts2.json.JSONResult"/>
        </result-types>
        <!-- 全局攔截器 -->
        <interceptors>
            <interceptor name="json" class="org.apache.struts2.json.JSONInterceptor"/>
            <interceptor name="globalErrInterceptor" class="com.hello.web.ErrorInterceptor"/>
            <interceptor-stack name="myDefaultStack">
                <!-- 自定義錯誤攔截器棧 -->
                <interceptor-ref name="globalErrInterceptor"/>
                <!-- struts2 提供的攔截器棧,包含了struts2的不少核心攔截器 -->  
                <interceptor-ref name="defaultStack" />
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myDefaultStack"/>
        <default-action-ref name="acctionNotFoundError"/>

        <global-results>
            <result name="jsonMsg" type="json">
                <param name="root">message</param>
            </result>
            <result name="error">/WEB-INF/pages/error/404.jsp</result>
            <result name="500">/WEB-INF/pages/error/500.jsp</result>
            <result name="index">/index.jsp</result>
            <result name="testMessage">/WEB-INF/pages/msg/message.jsp</result>
        </global-results>
        <!-- 全局異常配置 -->
        <global-exception-mappings>
            <exception-mapping result="500" exception="java.lang.Exception"/>
        </global-exception-mappings>
        <action name="index" class="com.hello.web.IndexAction" method="index">
            <result name="welcome">/index.jsp</result>
        </action>
        <!-- 使用 default-action-ref 配置struts2攔截到的404錯誤-->
        <action name="acctionNotFoundError" class="com.hello.web.PageNotFoundAction" method="go404Page">
            <result name="pageNotFound">/WEB-INF/pages/error/404.jsp</result>
        </action>
    </package>
    
    <!-- struts2 修改配置文件路徑後,必須加進來 有這裏看出,當前文件的路徑是跟路徑下classes路徑,因此其餘的文件要從classes這個路徑開始找 -->  
    <include file="struts-plugin.xml" />  
    <include file="struts-default.xml" />  
    <!-- 本身添加的配置文件  注意路徑 --> 
    <include file="../config/struts-i18n-test.xml" />  
    <include file="../config/struts-validate-test.xml" /> 
    <include file="../config/struts-tags-test.xml" />
    <include file="../config/struts-upload2download-test.xml" />
    
</struts>

struts-upload2download-test.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="fileUpload2download" extends="my-default" namespace="/file">
        <!-- 單文件上傳 -->
        <action name="fileUpload" class="com.hello.web.upAndDownload.FileUploadAction" method="uploadFile">
            <interceptor-ref name ="fileUpload"> 
                <!-- 默認1M 若是上傳文件在  maximumSize 和 struts.xml裏面配置的 struts.multipart.maxSize 之間-->
                <!-- 會提示struts.messages.error.file.too.large這個錯誤 -->
                <!-- 大於struts.multipart.maxSize 提示 struts.messages.upload.error.SizeLimitExceededException 這個錯誤 -->
                <param name="maximumSize">1048576</param>  
                <!-- 文件上傳容許類型 -->   
                <param name ="allowedTypes">image/bmp,image/png,image/gif,image/jpeg,image/jpg,text/plain</param>      
            </interceptor-ref>    
            <!-- 默認攔截器必須放在fileUpload以後  -->
            <interceptor-ref name ="defaultStack"/> 
            <!-- 出錯時跳轉頁面 -->
            <result name="input">/WEB-INF/pages/upload2down/upload.jsp</result>
            <!-- 上傳成功顯示頁面 -->
            <result name="success">/WEB-INF/pages/upload2down/uploadSuccess.jsp</result>
            <result name="uploadPage">/WEB-INF/pages/upload2down/upload.jsp</result>
        </action>
        <!-- 文件下載 -->
        <action name="fileDownload" class="com.hello.web.upAndDownload.FileDownLoadAction" method="download">
            <!-- 不指定result name 成功默認到success 出錯到 input -->
            <result name="success" type="stream">
                <!-- 下面這種方式也能避免亂碼 -->
                <!-- <param name="contentType">application/octet-stream;charset=ISO8859-1</param> -->
                <param name="contentType">application/octet-stream</param>
                <param name="inputName">inputStream</param>
                <!-- 至關於fileDownload.getDownloadFileName -->
                <param name="contentDisposition">attachment;filename="${downloadFileName}"</param>
                <param name="bufferSize">4096</param>
            </result>
        </action>
        <!-- 多文件上傳 -->
        <action name="multiFileUpload" class="com.hello.web.upAndDownload.MultiFileUploadAction" method="uploadFile">
            <interceptor-ref name ="fileUpload"> 
                <!-- 默認1M 若是上傳文件在  maximumSize 和 struts.xml裏面配置的 struts.multipart.maxSize 之間-->
                <!-- 會提示struts.messages.error.file.too.large這個錯誤 -->
                <!-- 大於struts.multipart.maxSize 提示 struts.messages.upload.error.SizeLimitExceededException 這個錯誤 -->
                <param name="maximumSize">1048576</param>  
                <!-- 文件上傳容許類型 -->   
                <param name ="allowedTypes">image/bmp,image/png,image/gif,image/jpeg,image/jpg,text/plain</param>      
            </interceptor-ref>    
            <!-- 默認攔截器必須放在fileUpload以後  -->
            <interceptor-ref name ="defaultStack"/> 
            <!-- 出錯時跳轉頁面 -->
            <result name="input">/WEB-INF/pages/upload2down/multiUpload.jsp</result>
            <!-- 上傳成功顯示頁面 -->
            <result name="success">/WEB-INF/pages/upload2down/multiUploadSuccess.jsp</result>
            <result name="multiUploadPage">/WEB-INF/pages/upload2down/multiUpload.jsp</result>
        </action>
        <action name="iframeFileUpload" class="com.hello.web.upAndDownload.FileUploadAction" method="iframeUpload">
            <interceptor-ref name ="fileUpload"> 
                <param name="maximumSize">1048576</param>  
                <param name ="allowedTypes">image/bmp,image/png,image/gif,image/jpeg,image/jpg,text/plain</param>      
            </interceptor-ref>    
            <interceptor-ref name ="defaultStack"/> 
            <result name="input">/WEB-INF/pages/upload2down/ajax1Upload.jsp</result>
            <!-- 上傳成功顯示頁面 -->
            <result name="success">/WEB-INF/pages/upload2down/ajax1Upload.jsp</result>
            <result name="iframeUpload">/WEB-INF/pages/upload2down/ajax1Upload.jsp</result>
        </action>
    </package>
</struts>
相關文章
相關標籤/搜索