struts2 用iframe 做个无刷新上传文件例子(一)

用Iframe来实现无刷新文件上传的注意点

1. 页面需要放一个iframe,并隐藏,然后让上传页面表单的target指定到这个iframe

2. struts2里面,中文文件编码处理,可以在配置文件,也可以在action取上传文件名字的地方,看下面代码。

3. 上传完成后,还是提交返回到上传页面,但是后台上传成功的提示信息回传时,在js 里面,都必须用parent.xxx的方式,才能访问到iframe外面的变量和js方法,有点嵌套的意思,比较搞。

4. 上传页面可以再放一个form,用来下载用。

5. struts2一般出错或者取不到值,都是对valueStack和ognl 理解不准确导致的,#号访问valuestack中非root节点的值,不用#访问的是action里面属性的值,因为action默认是这个valuestack的root节点。

6. struts2 action要取得属性值,前台form必须提交过去,就算没用到,就用隐藏域传,否则后台取回报空指针。多文件上传下载例子里有实例。

7. 无刷新上传,还是不要用iframe,太麻烦。尤其是js访问iframe外面的方法和变量,或者提交表单,全部要加parent

上代码

上传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>

转载于:https://my.oschina.net/sharkbobo/blog/226978

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值