`
flyingbin
  • 浏览: 10763 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

struts2上传文件,显示进度条

 
阅读更多
先看效果:









    在struts2中上传是很简单的,struts2会先把文件写到临时文件中,以后在提供这个文件的File对象到action中。具体原理看这里:

http://blog.csdn.net/tom_221x/archive/2009/01/12/3761390.aspx。



    利用servlet和common-upload.jar很容易实现显示文件上传的进度,在common-upload组件中实现一个ProgressListener接口,组件会把上传的实时进度传给你。但是想在struts2中,实时的显示进度是有些困难的。因为struts2把request对象给封装了,在Action中拿到request对象,如果是上传文件,那么struts2已经把文件写到文件系统里去了。





    struts2上传文件的时候封装request对象其实是org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper,也就是说在action中拿到的实际类型是MultiPartRequestWrapper。片段如下:

    [java] view plaincopyprint?public class MultiPartRequestWrapper extends StrutsRequestWrapper { 
    protected static final Logger LOG = LoggerFactory.getLogger(MultiPartRequestWrapper.class); 
    Collection<String> errors; 
    MultiPartRequest multi; 
    /**
     * Process file downloads and log any errors.
     *
     * @param request Our HttpServletRequest object
     * @param saveDir Target directory for any files that we save
     * @param multiPartRequest Our MultiPartRequest object
     */ 
    public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir) { 
        super(request); 
         
        multi = multiPartRequest; 
        try { 
            multi.parse(request, saveDir); 
            for (Object o : multi.getErrors()) { 
                String error = (String) o; 
                addError(error); 
            } 
        } catch (IOException e) { 
            addError("Cannot parse request: "+e.toString()); 
        }  
    } 
public class MultiPartRequestWrapper extends StrutsRequestWrapper {
    protected static final Logger LOG = LoggerFactory.getLogger(MultiPartRequestWrapper.class);
    Collection<String> errors;
    MultiPartRequest multi;
    /**
     * Process file downloads and log any errors.
     *
     * @param request Our HttpServletRequest object
     * @param saveDir Target directory for any files that we save
     * @param multiPartRequest Our MultiPartRequest object
     */
    public MultiPartRequestWrapper(MultiPartRequest multiPartRequest, HttpServletRequest request, String saveDir) {
        super(request);
       
        multi = multiPartRequest;
        try {
            multi.parse(request, saveDir);
            for (Object o : multi.getErrors()) {
                String error = (String) o;
                addError(error);
            }
        } catch (IOException e) {
            addError("Cannot parse request: "+e.toString());
        }
    }



可以看到在构造的时候,调用multi.parse(request, saveDir)把上传的数据给封装了。这个MultiPartRequest的解析功能是在struts-default.xml中配置的,如下:



[xhtml] view plaincopyprint?<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default"/> 
!-- 文件解析器类 --> 
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" /> 
 
!-- 这就是struts2的文件解析器设置 --> 
<constant name="struts.multipart.handler" value="jakarta" /> 
    <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="struts" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default"/>
<!-- 文件解析器类 -->
    <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default" />
   
<!-- 这就是struts2的文件解析器设置 -->
    <constant name="struts.multipart.handler" value="jakarta" />






现在的设想是,strut2不要帮我解析上传的文件,留到action中,我自己设置。所以我们要覆盖这是配置,如下:



[xhtml] view plaincopyprint?<!-- 重写文件上传解析方法  --> 
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="myRequestParser" 
class="com.*.*.utils.MyRequestParseWrapper" scope="default" optional="true" /> 
 
;constant name="struts.multipart.handler" value="myRequestParser" /> 
    <!-- 重写文件上传解析方法  -->
    <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="myRequestParser"
    class="com.*.*.utils.MyRequestParseWrapper" scope="default" optional="true" />

<constant name="struts.multipart.handler" value="myRequestParser" />



这个MyRequestParseWrapper如下:



[java] view plaincopyprint?/**
* 重写struts2的request封装类

* @author scott.Cgi
*/ 
public class MyRequestParseWrapper extends JakartaMultiPartRequest { 
    /*
     * (non-Javadoc)
     * @see
     * org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest#parse
     * (javax.servlet.http.HttpServletRequest, java.lang.String)
     */ 
    @Override 
    public void parse(HttpServletRequest servletRequest, String saveDir) 
            throws IOException { 
            //什么也不做  
    } 

/**
* 重写struts2的request封装类
*
* @author scott.Cgi
*/
public class MyRequestParseWrapper extends JakartaMultiPartRequest {
    /*
     * (non-Javadoc)
     * @see
     * org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest#parse
     * (javax.servlet.http.HttpServletRequest, java.lang.String)
     */
    @Override
    public void parse(HttpServletRequest servletRequest, String saveDir)
            throws IOException {
            //什么也不做
    }
}



这样一来,在action中拿到的request就是带有上传文件的了。







接下来,所以说实现原理,依然使用common-uplaod.jar组件:



1. 页面有2个iframe,一个上传数据,一个显示进度。

2. 当然有2个action,一个上传数据,一个回写进度。

3. 上传的时候首先请求的是更新进度的iframe, 这个iframe执行客户端js发起上传文件请求,第二个iframe开始上传数据。与此同时,第一个iframe开始回写进度。进度对象保存在session中,通过request的hashcode为key。进度从第一个进度iframe,传递到第二个上传iframe中,实现进度信息的通信。





说明一下,2个iframe是因为,request未结束,不可以向客户端写数据,所以文件超大,就会阻塞回写信息。

具体的上传我封装了一下,具体代码如下:



[java] view plaincopyprint?import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.PrintWriter; 
import java.util.List; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.apache.commons.fileupload.FileItem; 
import org.apache.commons.fileupload.ProgressListener; 
import org.apache.commons.fileupload.disk.DiskFileItemFactory; 
import org.apache.commons.fileupload.servlet.ServletFileUpload; 
import org.apache.log4j.Logger; 
/**
* upload file

* @author scott.Cgi
*/ 
public class UploadFile { 
    private static final Logger LOG = Logger.getLogger(UploadFile.class); 
    /**
     * 上传文件
     * 
     * @param request
     *            http request
     * @param response
     *            htp response
     * @throws IOException
     *             IOException
     */ 
    @SuppressWarnings("unchecked") 
    public static void upload(HttpServletRequest request, 
            HttpServletResponse response) throws IOException { 
        LOG.info("客户端提交类型: " + request.getContentType()); 
        if (request.getContentType() == null) { 
            throw new IOException( 
                    "the request doesn't contain a multipart/form-data stream"); 
        } 
         
        String key = request.getParameter("key"); 
        Progress p = (Progress)request.getSession().getAttribute(key); 
         
        // 设置上传文件总大小  
        p.setLength(request.getContentLength()); 
        LOG.info("上传文件大小为 : " + p.getLength()); 
        // 上传临时路径  
        String path = request.getSession().getServletContext().getRealPath("/"); 
        LOG.info("上传临时路径 : " + path); 
        // 设置上传工厂  
        DiskFileItemFactory factory = new DiskFileItemFactory(); 
        factory.setRepository(new File(path)); 
        // 阀值,超过这个值才会写到临时目录  
        factory.setSizeThreshold(1024 * 1024 * 10); 
        ServletFileUpload upload = new ServletFileUpload(factory); 
        // 最大上传限制  
        upload.setSizeMax(1024 * 1024 * 200); 
        // 设置监听器监听上传进度  
        upload.setProgressListener(p); 
        try { 
            LOG.info("解析上传文件...."); 
            List<FileItem> items = upload.parseRequest(request); 
             
            LOG.info("上传数据..."); 
            for (FileItem item : items) { 
                 
                // 非表单域  
                if (!item.isFormField()) { 
                    LOG.info("上传路径  : " + path + item.getName()); 
                    FileOutputStream fos = new FileOutputStream(path + item.getName()); 
                    // 文件全在内存中  
                    if (item.isInMemory()) { 
                        fos.write(item.get()); 
                        p.setComplete(true); 
                    } else { 
                        InputStream is = item.getInputStream(); 
                        byte[] buffer = new byte[1024]; 
                        int len; 
                        while ((len = is.read(buffer)) > 0) { 
                            fos.write(buffer, 0, len); 
                        } 
                        is.close(); 
                    } 
                    fos.close(); 
                    LOG.info("完成上传文件!"); 
                     
                    item.delete(); 
                    LOG.info("删除临时文件!"); 
                     
                    p.setComplete(true); 
                    LOG.info("更新progress对象状态为完成状态!"); 
                } 
            } 
        } catch (Exception e) { 
            LOG.error("上传文件出现异常, 错误原因 : " + e.getMessage()); 
            // 发生错误,进度信息对象设置为完成状态  
            p.setComplete(true); 
            request.getSession().removeAttribute(key); 
        } 
    } 
     
    /**
     * 执行客户端脚本
     * 
     * @param response
     *            http response
     * @param script
     *            javscript string
     * @throws IOException 
     *            IOException
     */  
    public static void execClientScript(HttpServletResponse resposne, 
            String script) throws IOException { 
         
        PrintWriter out = resposne.getWriter(); 
         
        out.println("<mce:script type='text/javascript'><!-- 
" + script + " 
// --></mce:script>");  
        // fix ie problem  
        out.println("---------------------------------------------------"); 
        out.println("---------------------------------------------------"); 
        out.println("---------------------------------------------------"); 
        out.println("---------------------------------------------------"); 
        out.println("---------------------------------------------------"); 
        out.println("---------------------------------------------------"); 
        out.println("---------------------------------------------------"); 
        out.flush(); 
    } 
    /**
     * 上传文件进度信息
     * 
     * @author wanglei
     * @version 0.1
     */ 
    public static class Progress implements ProgressListener { 
        // 文件总长度  
        private long length = 0; 
        // 已上传的文件长度  
        private long currentLength = 0; 
        // 上传是否完成  
        private boolean isComplete = false; 
        /*
         * (non-Javadoc)
         * @see org.apache.commons.fileupload.ProgressListener#update(long,
         * long, int)
         */ 
        @Override 
        public void update(long bytesRead, long contentLength, int items) { 
            this.currentLength = bytesRead; 
        } 
        /**
         * the getter method of length
         * 
         * @return the length
         */ 
        public long getLength() { 
            return length; 
        } 
        /**
         * the getter method of currentLength
         * 
         * @return the currentLength
         */ 
        public long getCurrentLength() { 
            return currentLength; 
        } 
        /**
         * the getter method of isComplete
         * 
         * @return the isComplete
         */ 
        public boolean isComplete() { 
            return isComplete; 
        } 
        /**
         * the setter method of the length
         * 
         * @param length
         *            the length to set
         */ 
        public void setLength(long length) { 
            this.length = length; 
        } 
        /**
         * the setter method of the currentLength
         * 
         * @param currentLength
         *            the currentLength to set
         */ 
        public void setCurrentLength(long currentLength) { 
            this.currentLength = currentLength; 
        } 
        /**
         * the setter method of the isComplete
         * 
         * @param isComplete
         *            the isComplete to set
         */ 
        public void setComplete(boolean isComplete) { 
            this.isComplete = isComplete; 
        } 
    } 

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.log4j.Logger;
/**
* upload file
*
* @author scott.Cgi
*/
public class UploadFile {
    private static final Logger LOG = Logger.getLogger(UploadFile.class);
    /**
     * 上传文件
     *
     * @param request
     *            http request
     * @param response
     *            htp response
     * @throws IOException
     *             IOException
     */
    @SuppressWarnings("unchecked")
    public static void upload(HttpServletRequest request,
            HttpServletResponse response) throws IOException {
        LOG.info("客户端提交类型: " + request.getContentType());
        if (request.getContentType() == null) {
            throw new IOException(
                    "the request doesn't contain a multipart/form-data stream");
        }
       
        String key = request.getParameter("key");
        Progress p = (Progress)request.getSession().getAttribute(key);
       
        // 设置上传文件总大小
        p.setLength(request.getContentLength());
        LOG.info("上传文件大小为 : " + p.getLength());
        // 上传临时路径
        String path = request.getSession().getServletContext().getRealPath("/");
        LOG.info("上传临时路径 : " + path);
        // 设置上传工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setRepository(new File(path));
        // 阀值,超过这个值才会写到临时目录
        factory.setSizeThreshold(1024 * 1024 * 10);
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 最大上传限制
        upload.setSizeMax(1024 * 1024 * 200);
        // 设置监听器监听上传进度
        upload.setProgressListener(p);
        try {
            LOG.info("解析上传文件....");
            List<FileItem> items = upload.parseRequest(request);
           
            LOG.info("上传数据...");
            for (FileItem item : items) {
               
                // 非表单域
                if (!item.isFormField()) {
                    LOG.info("上传路径  : " + path + item.getName());
                    FileOutputStream fos = new FileOutputStream(path + item.getName());
                    // 文件全在内存中
                    if (item.isInMemory()) {
                        fos.write(item.get());
                        p.setComplete(true);
                    } else {
                        InputStream is = item.getInputStream();
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = is.read(buffer)) > 0) {
                            fos.write(buffer, 0, len);
                        }
                        is.close();
                    }
                    fos.close();
                    LOG.info("完成上传文件!");
                   
                    item.delete();
                    LOG.info("删除临时文件!");
                   
                    p.setComplete(true);
                    LOG.info("更新progress对象状态为完成状态!");
                }
            }
        } catch (Exception e) {
            LOG.error("上传文件出现异常, 错误原因 : " + e.getMessage());
            // 发生错误,进度信息对象设置为完成状态
            p.setComplete(true);
            request.getSession().removeAttribute(key);
        }
    }
   
    /**
     * 执行客户端脚本
     *
     * @param response
     *            http response
     * @param script
     *            javscript string
     * @throws IOException
     *            IOException
     */
    public static void execClientScript(HttpServletResponse resposne,
            String script) throws IOException {
       
        PrintWriter out = resposne.getWriter();
       
        out.println("<mce:script type='text/javascript'><!--
" + script + "
// --></mce:script>");
        // fix ie problem
        out.println("---------------------------------------------------");
        out.println("---------------------------------------------------");
        out.println("---------------------------------------------------");
        out.println("---------------------------------------------------");
        out.println("---------------------------------------------------");
        out.println("---------------------------------------------------");
        out.println("---------------------------------------------------");
        out.flush();
    }
    /**
     * 上传文件进度信息
     *
     * @author wanglei
     * @version 0.1
     */
    public static class Progress implements ProgressListener {
        // 文件总长度
        private long length = 0;
        // 已上传的文件长度
        private long currentLength = 0;
        // 上传是否完成
        private boolean isComplete = false;
        /*
         * (non-Javadoc)
         * @see org.apache.commons.fileupload.ProgressListener#update(long,
         * long, int)
         */
        @Override
        public void update(long bytesRead, long contentLength, int items) {
            this.currentLength = bytesRead;
        }
        /**
         * the getter method of length
         *
         * @return the length
         */
        public long getLength() {
            return length;
        }
        /**
         * the getter method of currentLength
         *
         * @return the currentLength
         */
        public long getCurrentLength() {
            return currentLength;
        }
        /**
         * the getter method of isComplete
         *
         * @return the isComplete
         */
        public boolean isComplete() {
            return isComplete;
        }
        /**
         * the setter method of the length
         *
         * @param length
         *            the length to set
         */
        public void setLength(long length) {
            this.length = length;
        }
        /**
         * the setter method of the currentLength
         *
         * @param currentLength
         *            the currentLength to set
         */
        public void setCurrentLength(long currentLength) {
            this.currentLength = currentLength;
        }
        /**
         * the setter method of the isComplete
         *
         * @param isComplete
         *            the isComplete to set
         */
        public void setComplete(boolean isComplete) {
            this.isComplete = isComplete;
        }
    }
}




action代码:



[java] view plaincopyprint?import java.io.IOException; 
import com.ufinity.mars.utils.UploadFile; 
import com.ufinity.mars.utils.UploadFile.Progress; 
import com.ufinity.savor.service.FileService; 
/**
* file action

* @author scott.Cgi
*/ 
public class FileAction extends AbstractAction { 
    /** {field's description} */ 
    private static final long serialVersionUID = 6649027352616232244L; 
    private FileService fileService; 
    /**
     * 上传文件页面
     * 
     * @return page view
     */ 
    public String preupload() { 
        return SUCCESS; 
    } 
    /**
     * 上传文件
     * 
     * @return page view
     */ 
    public String uploadfile() { 
        try { 
            UploadFile.upload(this.request, this.response); 
        } catch (IOException e) { 
            LOG.error("上传文件发生异常,错误原因 : " + e.getMessage()); 
        } 
        return null; 
    } 
    /**
     * 显示上传文件进度进度
     * 
     * @return page view
     */ 
    public String progress() { 
        String callback1 = this.request.getParameter("callback1"); 
        String callback2 = this.request.getParameter("callback2"); 
        // 缓存progress对象的key值  
        String key = Integer.toString(request.hashCode()); 
        // 新建当前上传文件的进度信息对象  
        Progress p = new Progress(); 
        // 缓存progress对象  
        this.request.getSession().setAttribute(key, p); 
         
         
        response.setContentType("text/html;charset=UTF-8"); 
        response.setHeader("pragma", "no-cache"); 
        response.setHeader("cache-control", "no-cache"); 
        response.setHeader("expires", "0"); 
        try { 
            UploadFile.execClientScript(response, callback1 + "(" + key + ")"); 
            long temp = 0l; 
            while (!p.isComplete()) { 
                if (temp != p.getCurrentLength()) { 
                    temp = p.getCurrentLength(); 
                    // 向客户端显示进度  
                    UploadFile.execClientScript(response, callback2 + "(" 
                            + p.getCurrentLength() + "," + p.getLength() + ")"); 
                     
                } else { 
                    //LOG.info("progress的状态 :" + p.isComplete());  
                    //LOG.info("progress上传的数据量 :+ " + p.getCurrentLength());  
                    //上传进度没有变化时候,不向客户端写数据,写数据过于频繁会让chrome没响应  
                    Thread.sleep(300); 
                } 
                 
            } 
             
        } catch (Exception e) { 
            LOG.error("调用客户端脚本错误,原因 :" + e.getMessage()); 
            p.setComplete(true); 
             
        } 
         
        this.request.getSession().removeAttribute(key); 
        LOG.info("删除progress对象的session key"); 
         
        return null; 
    } 
    /**
     * the getter method of fileService
     * 
     * @return the fileService
     */ 
    public FileService getFileService() { 
        return fileService; 
    } 
    /**
     * the setter method of the fileService
     * 
     * @param fileService
     *            the fileService to set
     */ 
    public void setFileService(FileService fileService) { 
        this.fileService = fileService; 
    } 

import java.io.IOException;
import com.ufinity.mars.utils.UploadFile;
import com.ufinity.mars.utils.UploadFile.Progress;
import com.ufinity.savor.service.FileService;
/**
* file action
*
* @author scott.Cgi
*/
public class FileAction extends AbstractAction {
    /** {field's description} */
    private static final long serialVersionUID = 6649027352616232244L;
    private FileService fileService;
    /**
     * 上传文件页面
     *
     * @return page view
     */
    public String preupload() {
        return SUCCESS;
    }
    /**
     * 上传文件
     *
     * @return page view
     */
    public String uploadfile() {
        try {
            UploadFile.upload(this.request, this.response);
        } catch (IOException e) {
            LOG.error("上传文件发生异常,错误原因 : " + e.getMessage());
        }
        return null;
    }
    /**
     * 显示上传文件进度进度
     *
     * @return page view
     */
    public String progress() {
        String callback1 = this.request.getParameter("callback1");
        String callback2 = this.request.getParameter("callback2");
        // 缓存progress对象的key值
        String key = Integer.toString(request.hashCode());
        // 新建当前上传文件的进度信息对象
        Progress p = new Progress();
        // 缓存progress对象
        this.request.getSession().setAttribute(key, p);
       
       
        response.setContentType("text/html;charset=UTF-8");
        response.setHeader("pragma", "no-cache");
        response.setHeader("cache-control", "no-cache");
        response.setHeader("expires", "0");
        try {
            UploadFile.execClientScript(response, callback1 + "(" + key + ")");
            long temp = 0l;
            while (!p.isComplete()) {
                if (temp != p.getCurrentLength()) {
                    temp = p.getCurrentLength();
                    // 向客户端显示进度
                    UploadFile.execClientScript(response, callback2 + "("
                            + p.getCurrentLength() + "," + p.getLength() + ")");
                   
                } else {
                    //LOG.info("progress的状态 :" + p.isComplete());
                    //LOG.info("progress上传的数据量 :+ " + p.getCurrentLength());
                    //上传进度没有变化时候,不向客户端写数据,写数据过于频繁会让chrome没响应
                    Thread.sleep(300);
                }
               
            }
           
        } catch (Exception e) {
            LOG.error("调用客户端脚本错误,原因 :" + e.getMessage());
            p.setComplete(true);
           
        }
       
        this.request.getSession().removeAttribute(key);
        LOG.info("删除progress对象的session key");
       
        return null;
    }
    /**
     * the getter method of fileService
     *
     * @return the fileService
     */
    public FileService getFileService() {
        return fileService;
    }
    /**
     * the setter method of the fileService
     *
     * @param fileService
     *            the fileService to set
     */
    public void setFileService(FileService fileService) {
        this.fileService = fileService;
    }
}




页面代码:



[xhtml] view plaincopyprint?    <mce:style type="text/css"><!-- 
        iframe{ 
            border:none; 
            width:0; 
            height:0; 
        } 
         
        #p_out{ 
          width:200px; 
          height:12px; 
          margin:10px 0 0 0; 
          padding:1px; 
          font-size:10px; 
          border:solid #6b8e23 1px; 
        } 
         
        #p_in{ 
          width:0%; 
          height:100%; 
          background-color:#6b8e23; 
          margin:0; 
          padding:0; 
        } 
         
        #dis{ 
          margin:0; 
          padding:0; 
          text-align:center; 
          font-size:12px; 
          height:12px; 
          width:200px; 
        } 
         
--></mce:style><style type="text/css" mce_bogus="1">     iframe{ 
            border:none; 
            width:0; 
            height:0; 
        } 
         
        #p_out{ 
          width:200px; 
          height:12px; 
          margin:10px 0 0 0; 
          padding:1px; 
          font-size:10px; 
          border:solid #6b8e23 1px; 
        } 
         
        #p_in{ 
          width:0%; 
          height:100%; 
          background-color:#6b8e23; 
          margin:0; 
          padding:0; 
        } 
         
        #dis{ 
          margin:0; 
          padding:0; 
          text-align:center; 
          font-size:12px; 
          height:12px; 
          width:200px; 
        } 
        </style> 
    </head> 
    <body> 
        <div class="main"> 
         
        <div class="top"> 
           <jsp:include page="/top.jsp" /> 
        </div> 
         
        <div style="width: 250px; margin: 0 auto;"> 
         
       
           <div class="errorbox"> 
                <s:actionerror/> 
           </div> 
             
           <form id="uploadfile_form" name="uploadfile_form" enctype="multipart/form-data"   
                 method="post" target="uploadfile_iframe">   
            
                <input type="file" name="file" />   
                <br><br>   
                <button onclick="progress()">提交</button>   
            
                <div id="p_out"><div id="p_in"></div></div>   
                <div id="dis"></div>   
           </form>   
            
           <iframe frameborder="0" id="uploadfile_iframe" name="uploadfile_iframe" src="javascript:void(0)" mce_src="javascript:void(0)"></iframe>   
           <iframe frameborder="0" id="progress_iframe" name="progress_iframe" src="javascript:void(0)" mce_src="javascript:void(0)"></iframe>   
        </div> 
         
        </div> 
         
    </body> 
     
    <mce:script type="text/javascript"><!-- 
    //上传文件 
    function uploadFile(key){ 
        document.forms[0].action = 'uploadfile.action?callback=parent.upload&key='+key; 
        document.forms[0].submit(); 
        document.getElementById('dis').innerHTML = "开始传送数据..."; 
         
    } 
    //获取文件上传进度 
    function progress(){ 
        document.getElementById('progress_iframe').src = 'progress.action?callback1=parent.uploadFile&callback2=parent.upload'; 
        document.getElementById('dis').innerHTML = '初始化数据...'; 
        document.getElementById('p_in').style.width = "0%"; 
    } 
    //更新进度 
    function upload(len, total){ 
        document.getElementById('p_in').style.width = (Math.round(len/total*100))+'%'; 
        document.getElementById('dis').innerHTML = len + '/' + total + ' Byte'; 
        if(len === total) { 
            document.getElementById('dis').innerHTML = "文件上传完成!"; 
        } 
    }     
     
     
// --></mce:script> 
</html> 
<mce:style type="text/css"><!--
iframe{
    border:none;
    width:0;
    height:0;
    }
   
    #p_out{
      width:200px;
  height:12px;
  margin:10px 0 0 0;
  padding:1px;
  font-size:10px;
  border:solid #6b8e23 1px;
    }
   
#p_in{
      width:0%;
  height:100%;
  background-color:#6b8e23;
  margin:0;
  padding:0;
    }
   
#dis{
      margin:0;
  padding:0;
  text-align:center;
  font-size:12px;
  height:12px;
  width:200px;
}

--></mce:style><style type="text/css" mce_bogus="1"> iframe{
    border:none;
    width:0;
    height:0;
    }
   
    #p_out{
      width:200px;
  height:12px;
  margin:10px 0 0 0;
  padding:1px;
  font-size:10px;
  border:solid #6b8e23 1px;
    }
   
#p_in{
      width:0%;
  height:100%;
  background-color:#6b8e23;
  margin:0;
  padding:0;
    }
   
#dis{
      margin:0;
  padding:0;
  text-align:center;
  font-size:12px;
  height:12px;
  width:200px;
}
</style>
    </head>
    <body>
        <div class="main">
       
        <div class="top">
           <jsp:include page="/top.jsp" />
        </div>
       
        <div style="width: 250px; margin: 0 auto;">
       
     
           <div class="errorbox">
                <s:actionerror/>
           </div>
           
           <form id="uploadfile_form" name="uploadfile_form" enctype="multipart/form-data" 
      method="post" target="uploadfile_iframe"> 
          
         <input type="file" name="file" /> 
         <br><br> 
         <button onclick="progress()">提交</button> 
          
         <div id="p_out"><div id="p_in"></div></div> 
         <div id="dis"></div> 
        </form> 
       
        <iframe frameborder="0" id="uploadfile_iframe" name="uploadfile_iframe" src="javascript:void(0)" mce_src="javascript:void(0)"></iframe> 
           <iframe frameborder="0" id="progress_iframe" name="progress_iframe" src="javascript:void(0)" mce_src="javascript:void(0)"></iframe> 
        </div>
       
        </div>
       
    </body>
   
    <mce:script type="text/javascript"><!--
    //上传文件
  function uploadFile(key){
  document.forms[0].action = 'uploadfile.action?callback=parent.upload&key='+key;
  document.forms[0].submit();
  document.getElementById('dis').innerHTML = "开始传送数据...";

}
  //获取文件上传进度
function progress(){
document.getElementById('progress_iframe').src = 'progress.action?callback1=parent.uploadFile&callback2=parent.upload';
document.getElementById('dis').innerHTML = '初始化数据...';
document.getElementById('p_in').style.width = "0%";
}
//更新进度
function upload(len, total){
document.getElementById('p_in').style.width = (Math.round(len/total*100))+'%';
document.getElementById('dis').innerHTML = len + '/' + total + ' Byte';
if(len === total) {
document.getElementById('dis').innerHTML = "文件上传完成!";
}
}   

   
// --></mce:script>
</html>






注意: common-upload.jar依赖common-io.jar

  • 大小: 2.7 KB
2
4
分享到:
评论

相关推荐

    pandas-1.3.5-cp37-cp37m-macosx_10_9_x86_64.zip

    pandas whl安装包,对应各个python版本和系统(具体看资源名字),找准自己对应的下载即可! 下载后解压出来是已.whl为后缀的安装包,进入终端,直接pip install pandas-xxx.whl即可,非常方便。 再也不用担心pip联网下载网络超时,各种安装不成功的问题。

    基于java的大学生兼职信息系统答辩PPT.pptx

    基于java的大学生兼职信息系统答辩PPT.pptx

    基于java的乐校园二手书交易管理系统答辩PPT.pptx

    基于java的乐校园二手书交易管理系统答辩PPT.pptx

    tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl

    tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl

    Android Studio Ladybug(android-studio-2024.2.1.10-mac.zip.002)

    Android Studio Ladybug 2024.2.1(android-studio-2024.2.1.10-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/89954174 part2: https://download.csdn.net/download/weixin_43800734/89954175

    基于ssm框架+mysql+jsp实现的监考安排与查询系统

    有学生和教师两种角色 登录和注册模块 考场信息模块 考试信息模块 点我收藏 功能 监考安排模块 考场类型模块 系统公告模块 个人中心模块: 1、修改个人信息,可以上传图片 2、我的收藏列表 账号管理模块 服务模块 eclipse或者idea 均可以运行 jdk1.8 apache-maven-3.6 mysql5.7及以上 tomcat 8.0及以上版本

    tornado-6.1b2-cp38-cp38-macosx_10_9_x86_64.whl

    tornado-6.1b2-cp38-cp38-macosx_10_9_x86_64.whl

    Android Studio Ladybug(android-studio-2024.2.1.10-mac.zip.001)

    Android Studio Ladybug 2024.2.1(android-studio-2024.2.1.10-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/89954174 part2: https://download.csdn.net/download/weixin_43800734/89954175

    基于MATLAB车牌识别代码实现代码【含界面GUI】.zip

    matlab

    基于java的毕业生就业信息管理系统答辩PPT.pptx

    基于java的毕业生就业信息管理系统答辩PPT.pptx

    基于Web的毕业设计选题系统的设计与实现(springboot+vue+mysql+说明文档).zip

    随着高等教育的普及和毕业设计的日益重要,为了方便教师、学生和管理员进行毕业设计的选题和管理,我们开发了这款基于Web的毕业设计选题系统。 该系统主要包括教师管理、院系管理、学生管理等多个模块。在教师管理模块中,管理员可以新增、删除教师信息,并查看教师的详细资料,方便进行教师资源的分配和管理。院系管理模块则允许管理员对各个院系的信息进行管理和维护,确保信息的准确性和完整性。 学生管理模块是系统的核心之一,它提供了学生选题、任务书管理、开题报告管理、开题成绩管理等功能。学生可以在此模块中进行毕业设计的选题,并上传任务书和开题报告,管理员和教师则可以对学生的报告进行审阅和评分。 此外,系统还具备课题分类管理和课题信息管理功能,方便对毕业设计课题进行分类和归档,提高管理效率。在线留言功能则为学生、教师和管理员提供了一个交流互动的平台,可以就毕业设计相关问题进行讨论和解答。 整个系统设计简洁明了,操作便捷,大大提高了毕业设计的选题和管理效率,为高等教育的发展做出了积极贡献。

    机器学习(预测模型):2000年至2015年期间193个国家的预期寿命和相关健康因素的数据

    这个数据集来自世界卫生组织(WHO),包含了2000年至2015年期间193个国家的预期寿命和相关健康因素的数据。它提供了一个全面的视角,用于分析影响全球人口预期寿命的多种因素。数据集涵盖了从婴儿死亡率、GDP、BMI到免疫接种覆盖率等多个维度,为研究者提供了丰富的信息来探索和预测预期寿命。 该数据集的特点在于其跨国家的比较性,使得研究者能够识别出不同国家之间预期寿命的差异,并分析这些差异背后的原因。数据集包含22个特征列和2938行数据,涉及的变量被分为几个大类:免疫相关因素、死亡因素、经济因素和社会因素。这些数据不仅有助于了解全球健康趋势,还可以辅助制定公共卫生政策和社会福利计划。 数据集的处理包括对缺失值的处理、数据类型转换以及去重等步骤,以确保数据的准确性和可靠性。研究者可以使用这个数据集来探索如教育、健康习惯、生活方式等因素如何影响人们的寿命,以及不同国家的经济发展水平如何与预期寿命相关联。此外,数据集还可以用于预测模型的构建,通过回归分析等统计方法来预测预期寿命。 总的来说,这个数据集是研究全球健康和预期寿命变化的宝贵资源,它不仅提供了历史数据,还为未来的研究和政策制

    基于微信小程序的高校毕业论文管理系统小程序答辩PPT.pptx

    基于微信小程序的高校毕业论文管理系统小程序答辩PPT.pptx

    基于java的超市 Pos 收银管理系统答辩PPT.pptx

    基于java的超市 Pos 收银管理系统答辩PPT.pptx

    基于java的网上报名系统答辩PPT.pptx

    基于java的网上报名系统答辩PPT.pptx

    基于java的网上书城答辩PPT.pptx

    基于java的网上书城答辩PPT.pptx

    婚恋网站 SSM毕业设计 附带论文.zip

    婚恋网站 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B

    基于java的戒烟网站答辩PPT.pptx

    基于java的戒烟网站答辩PPT.pptx

    基于微信小程序的“健康早知道”微信小程序答辩PPT.pptx

    基于微信小程序的“健康早知道”微信小程序答辩PPT.pptx

    机器学习(预测模型):自行车共享使用情况的数据集

    Capital Bikeshare 数据集是一个包含从2020年5月到2024年8月的自行车共享使用情况的数据集。这个数据集记录了华盛顿特区Capital Bikeshare项目中自行车的租赁模式,包括了骑行的持续时间、开始和结束日期时间、起始和结束站点、使用的自行车编号、用户类型(注册会员或临时用户)等信息。这些数据可以帮助分析和预测自行车共享系统的需求模式,以及了解用户行为和偏好。 数据集的特点包括: 时间范围:覆盖了四年多的时间,提供了长期的数据观察。 细节丰富:包含了每次骑行的详细信息,如日期、时间、天气条件、季节等,有助于深入分析。 用户分类:数据中区分了注册用户和临时用户,可以分析不同用户群体的使用习惯。 天气和季节因素:包含了天气情况和季节信息,可以研究这些因素对骑行需求的影响。 通过分析这个数据集,可以得出关于自行车共享使用模式的多种见解,比如一天中不同时间段的使用高峰、不同天气条件下的使用差异、季节性变化对骑行需求的影响等。这些信息对于城市规划者、交通管理者以及自行车共享服务提供商来说都是非常宝贵的,可以帮助他们优化服务、提高效率和满足用户需求。同时,这个数据集也

Global site tag (gtag.js) - Google Analytics