Struts2上传文件进度条

    这几天由于需要开始着手实现Struts上传文件的进度条,中途参考了许多大佬的文章,折腾了好几天终于是给弄出来了。就想写篇博客给记录一下免得自己又忘了。在实现的过程中遇到了不少bug,不过幸好没放弃。不多说,直接开始!

解决方案的基本思路是这样的:

  •   在Form提交上传文件同时,使用AJAX周期性地从Action轮询上传状态信息
  •   然后,根据此信息更新进度条和相关文字,及时反映文件传输状态
    首先,我们要如何获取上传进度信息呢

    查阅一下资料了解到Struts2对文件上传的request请求做了封装,也就是说在调用上传文件的action时就已经上传temp完成了。 那我们就在它的request类中给它添加一个ProgressListener来监控进度,Struts2中request类是没有ProgressListener。到这想到的就是重写它的request类:org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest; 可这个类中许多方法是Pirvate的,就是说我们并不能通过继承来重写它的方法。查阅了网上的方法,发现可以通过自定义JakartaMultiPartRequest来阻止Struts2调用它自己的JakartaMultiPartRequest。

    那么,开始:自定义JakartaMultiPartRequest
    首先把它的源码都复制过来,JakartaMultiPartRequest源码如下:
package org.apache.struts2.dispatcher.multipart;

import com.opensymphony.xwork2.LocaleProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.struts2.StrutsConstants;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

/**
 * Multipart form data request adapter for Jakarta Commons Fileupload package.
 */
public class JakartaMultiPartRequest implements MultiPartRequest {

    static final Logger LOG = LoggerFactory.getLogger(JakartaMultiPartRequest.class);

    // maps parameter name -> List of FileItem objects
    protected Map<String, List<FileItem>> files = new HashMap<String, List<FileItem>>();

    // maps parameter name -> List of param values
    protected Map<String, List<String>> params = new HashMap<String, List<String>>();

    // any errors while processing this request
    protected List<String> errors = new ArrayList<String>();

    protected long maxSize;
    private Locale defaultLocale = Locale.ENGLISH;

    @Inject(StrutsConstants.STRUTS_MULTIPART_MAXSIZE)
    public void setMaxSize(String maxSize) {
        this.maxSize = Long.parseLong(maxSize);
    }

    @Inject
    public void setLocaleProvider(LocaleProvider provider) {
        defaultLocale = provider.getLocale();
    }

    /**
     * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
     * multipart classes (see class description).
     *
     * @param saveDir the directory to save off the file
     * @param request the request containing the multipart
     * @throws java.io.IOException is thrown if encoding fails.
     */
    public void parse(HttpServletRequest request, String saveDir) throws IOException {
        try {
            setLocale(request);
            processUpload(request, saveDir);
        } catch (FileUploadBase.SizeLimitExceededException e) {
            if (LOG.isWarnEnabled()) {
                LOG.warn("Request exceeded size limit!", e);
            }
            String errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()});
            if (!errors.contains(errorMessage)) {
                errors.add(errorMessage);
            }
        } catch (Exception e) {
            if (LOG.isWarnEnabled()) {
                LOG.warn("Unable to parse request", e);
            }
            String errorMessage = buildErrorMessage(e, new Object[]{});
            if (!errors.contains(errorMessage)) {
                errors.add(errorMessage);
            }
        }
    }

    protected void setLocale(HttpServletRequest request) {
        if (defaultLocale == null) {
            defaultLocale = request.getLocale();
        }
    }

    protected String buildErrorMessage(Throwable e, Object[] args) {
        String errorKey = "struts.messages.upload.error." + e.getClass().getSimpleName();
        if (LOG.isDebugEnabled()) {
            LOG.debug("Preparing error message for key: [#0]", errorKey);
        }
        return LocalizedTextUtil.findText(this.getClass(), errorKey, defaultLocale, e.getMessage(), args);
    }

    private void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException {
        for (FileItem item : parseRequest(request, saveDir)) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Found item " + item.getFieldName());
            }
            if (item.isFormField()) {
                processNormalFormField(item, request.getCharacterEncoding());
            } else {
                processFileField(item);
            }
        }
    }

    private void processFileField(FileItem item) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Item is a file upload");
        }

        // Skip file uploads that don't have a file name - meaning that no file was selected.
        if (item.getName() == null || item.getName().trim().length() < 1) {
            LOG.debug("No file has been uploaded for the field: " + item.getFieldName());
            return;
        }

        List<FileItem> values;
        if (files.get(item.getFieldName()) != null) {
            values = files.get(item.getFieldName());
        } else {
            values = new ArrayList<FileItem>();
        }

        values.add(item);
        files.put(item.getFieldName(), values);
    }

    private void processNormalFormField(FileItem item, String charset) throws UnsupportedEncodingException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("Item is a normal form field");
        }
        List<String> values;
        if (params.get(item.getFieldName()) != null) {
            values = params.get(item.getFieldName());
        } else {
            values = new ArrayList<String>();
        }

        // note: see http://jira.opensymphony.com/browse/WW-633
        // basically, in some cases the charset may be null, so
        // we're just going to try to "other" method (no idea if this
        // will work)
        if (charset != null) {
            values.add(item.getString(charset));
        } else {
            values.add(item.getString());
        }
        params.put(item.getFieldName(), values);
        item.delete();
    }

    private List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
        DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
        ServletFileUpload upload = new ServletFileUpload(fac);
        upload.setSizeMax(maxSize);
        return upload.parseRequest(createRequestContext(servletRequest));
    }

    private DiskFileItemFactory createDiskFileItemFactory(String saveDir) {
        DiskFileItemFactory fac = new DiskFileItemFactory();
        // Make sure that the data is written to file
        fac.setSizeThreshold(0);
        if (saveDir != null) {
            fac.setRepository(new File(saveDir));
        }
        return fac;
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileParameterNames()
     */
    public Enumeration<String> getFileParameterNames() {
        return Collections.enumeration(files.keySet());
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)
     */
    public String[] getContentType(String fieldName) {
        List<FileItem> items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List<String> contentTypes = new ArrayList<String>(items.size());
        for (FileItem fileItem : items) {
            contentTypes.add(fileItem.getContentType());
        }

        return contentTypes.toArray(new String[contentTypes.size()]);
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)
     */
    public File[] getFile(String fieldName) {
        List<FileItem> items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List<File> fileList = new ArrayList<File>(items.size());
        for (FileItem fileItem : items) {
            File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
            if (fileItem.isInMemory() && storeLocation != null && !storeLocation.exists()) {
                try {
                    storeLocation.createNewFile();
                } catch (IOException e) {
                    if (LOG.isErrorEnabled()) {
                        LOG.error("Cannot write uploaded empty file to disk: " + storeLocation.getAbsolutePath(), e);
                    }
                }
            }
            fileList.add(storeLocation);
        }

        return fileList.toArray(new File[fileList.size()]);
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFileNames(java.lang.String)
     */
    public String[] getFileNames(String fieldName) {
        List<FileItem> items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List<String> fileNames = new ArrayList<String>(items.size());
        for (FileItem fileItem : items) {
            fileNames.add(getCanonicalName(fileItem.getName()));
        }

        return fileNames.toArray(new String[fileNames.size()]);
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)
     */
    public String[] getFilesystemName(String fieldName) {
        List<FileItem> items = files.get(fieldName);

        if (items == null) {
            return null;
        }

        List<String> fileNames = new ArrayList<String>(items.size());
        for (FileItem fileItem : items) {
            fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
        }

        return fileNames.toArray(new String[fileNames.size()]);
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)
     */
    public String getParameter(String name) {
        List<String> v = params.get(name);
        if (v != null && v.size() > 0) {
            return v.get(0);
        }

        return null;
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterNames()
     */
    public Enumeration<String> getParameterNames() {
        return Collections.enumeration(params.keySet());
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameterValues(java.lang.String)
     */
    public String[] getParameterValues(String name) {
        List<String> v = params.get(name);
        if (v != null && v.size() > 0) {
            return v.toArray(new String[v.size()]);
        }

        return null;
    }

    /* (non-Javadoc)
     * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getErrors()
     */
    public List<String> getErrors() {
        return errors;
    }

    /**
     * Returns the canonical name of the given file.
     *
     * @param filename the given file
     * @return the canonical name of the given file
     */
    private String getCanonicalName(String filename) {
        int forwardSlash = filename.lastIndexOf("/");
        int backwardSlash = filename.lastIndexOf("\\");
        if (forwardSlash != -1 && forwardSlash > backwardSlash) {
            filename = filename.substring(forwardSlash + 1, filename.length());
        } else if (backwardSlash != -1 && backwardSlash >= forwardSlash) {
            filename = filename.substring(backwardSlash + 1, filename.length());
        }

        return filename;
    }

    /**
     * Creates a RequestContext needed by Jakarta Commons Upload.
     *
     * @param req the request.
     * @return a new request context.
     */
    private RequestContext createRequestContext(final HttpServletRequest req) {
        return new RequestContext() {
            public String getCharacterEncoding() {
                return req.getCharacterEncoding();
            }

            public String getContentType() {
                return req.getContentType();
            }

            public int getContentLength() {
                return req.getContentLength();
            }

            public InputStream getInputStream() throws IOException {
                InputStream in = req.getInputStream();
                if (in == null) {
                    throw new IOException("Missing content in the request");
                }
                return req.getInputStream();
            }
        };
    }

    /* (non-Javadoc)
    * @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#cleanUp()
    */
    public void cleanUp() {
        Set<String> names = files.keySet();
        for (String name : names) {
            List<FileItem> items = files.get(name);
            for (FileItem item : items) {
                if (LOG.isDebugEnabled()) {
                    String msg = LocalizedTextUtil.findText(this.getClass(), "struts.messages.removing.file",
                            Locale.ENGLISH, "no.message.found", new Object[]{name, item});
                    LOG.debug(msg);
                }
                if (!item.isInMemory()) {
                    item.delete();
                }
            }
        }
    }

}
把以上 JakartaMultiPartRequest类体中的源码直接复制粘贴到自定义的 MultiPartRequest(我的自定义类名) 类中,接着就可以Ctrl+f 查找到parserRequest(),也就是上面源码中红色标记的部分,如下添加几行代码(红色标记部分),实际上就是添加一个ProgressListener。
 private List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
	    	System.out.println("调用parseRequest方法");
	    	UploadProgressListener listener = new UploadProgressListener(servletRequest);
	    	DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
	        ServletFileUpload upload = new ServletFileUpload(fac);
	        upload.setSizeMax(maxSize);
	        upload.setProgressListener(listener);
	        System.out.println("设置监听器成功");
	        return upload.parseRequest(createRequestContext(servletRequest));
	    }
以上修改完成后,就该到Struts.xml中配置我们自定义的 MultiPartRequest。
Struts.xml配置:
<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
 	name="myRequestParser" class="com.plat.utils.MutipartRequest"  
 	scope="default" optional="true"></bean>  
<constant name="struts.multipart.parser" value="myRequestParser"/>

在Struts中添加以上几行代码。需要注意的一点是Struts2.3.15.1版本以前红色标记部分为Struts.multipart.handler,Struts2.3.15.1(包括2.3.15.1)为Struts.multipart.parser

现在我们就该实现在parserRequest()中定义的监听器了:

这个监听器需要实现org.apache.commons.fileupload.ProgressListener这个接口,直接implements就行。在update方法中我们可以获取到已上传的文件长度,上传的文件的总长度,当前上传第几个文件。在update方法中设置了文件上传状态实体类的实例,并且保存到session,这一步是能让前端使用ajax访问到文件当前的上传进度信息

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.ProgressListener;

/**
 * Created by xer on 2018/06/23.
 * 监听文件上传情况
 * 实现org.apache.commons.fileupload.ProgressListener接口
 */
public class UploadProgressListener implements ProgressListener{
	private HttpSession session;//创建监听器实例的时候获取session

    //在自定义的MultiPartRequest 类中 创建此监听器的实例
    public UploadProgressListener(HttpServletRequest request) {
    	System.out.println("");
        session = request.getSession();
        FileUploadProgress fileUploadProgress = new FileUploadProgress();
        fileUploadProgress.setFlag(false);
        session.setAttribute("fileUploadProgress", fileUploadProgress);
    }
    public void update(long readBytes, long totalBytes, int currentItem) {
        //实现文件上传的核心方法
        Object attribute = session.getAttribute("fileUploadProgress");
//        System.out.println("当前已读取:"+readBytes+" 总长度:"+totalBytes+" 正在保存:"+currentItem);
        FileUploadProgress fileUploadProgress;
        if(null == attribute){
            fileUploadProgress = new FileUploadProgress();
            fileUploadProgress.setFlag(false);
            System.out.println("uploadListener文件上传的开始时间:"+fileUploadProgress.getStartTime());
            session.setAttribute("fileUploadProgress", fileUploadProgress);
        }else{
            fileUploadProgress = (FileUploadProgress)attribute;
        }
        fileUploadProgress.setCurrentLength(readBytes);
        fileUploadProgress.setTotalLength(totalBytes);
        if(readBytes==totalBytes){
            fileUploadProgress.setFlag(true);
        }else{
            fileUploadProgress.setFlag(false);
        }
        session.setAttribute("fileUploadProgress", fileUploadProgress);
    }
}
接下来是文件上传实体类:
public class FileUploadProgress {
	 private long startTime = System.currentTimeMillis();//开始时间
	    private long totalLength=1;//文件上传的总长度
	    private long currentLength=0;//当前文件上传的长度
	    private boolean flag;//是否上传完成

	    public long getTotalLength() {
	        return totalLength;
	    }

	    public void setTotalLength(long totalLength) {
	        this.totalLength = totalLength;
	    }

	    public long getCurrentLength() {
	        return currentLength;
	    }

	    public void setCurrentLength(long currentLength) {
	        this.currentLength = currentLength;
	    }

	    public boolean isFlag() {
	        return flag;
	    }

	    public void setFlag(boolean flag) {
	        this.flag = flag;
	    }

	    public long getStartTime() {
	        return startTime;
	    }

	    public void setStartTime(long startTime) {
	        this.startTime = startTime;
	    }

	    public FileUploadProgress(){
	        super();
	    }
}
到这我们准备的就差不多了,现在只要实现两个Action即可:一个用于上传文件,一个用于上传文件时实时的返回上传进度给前端Ajax。 这里我们使用的是返回json数据,需要用到Struts-json-plugin-2.3.16.jar
监控上传进度Action:
package com.plat.action;

import java.util.HashMap;
import java.util.Map;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.Action;
import com.plat.utils.DataUtil;
import com.plat.utils.FileUploadProgress;

public class ProgressAction implements Action{
	private Map<String,Object> jsonData;
	
	public String execute() throws Exception {
		System.out.println("获取上传文件进度信息");
        jsonData = new HashMap(); 	//初始化jsonData
        FileUploadProgress p;
        Object attribute = ServletActionContext.getRequest().getSession().getAttribute("fileUploadProgress");
        if(null == attribute){
            System.out.println("session中没有fileupload信息1");
            jsonData.put("completed", false);
            jsonData.put("isStarted", false);
            setJsonData(jsonData);
            return SUCCESS;
        }else{
            System.out.println("session中有fileupload信息2");
            p = (FileUploadProgress)attribute;
        }

        System.out.println("action中获取到的文件上传的开始时间:"+p.getStartTime());
        System.out.println("action运行到这里的时间:"+System.currentTimeMillis());
        long time = (System.currentTimeMillis() - p.getStartTime())/ 1000 + 1; //已传输的时间 单位:s

        System.out.println("截至目前上传时间:"+time);

        double v = ((double)p.getCurrentLength()) / (double)time; // b/s
        System.out.println("传输速度:"+v);
        System.out.println("pAction:当前上传--"+p.getCurrentLength());

        jsonData.put("percent", DataUtil.percent(p.getCurrentLength(),p.getTotalLength()));
        System.out.println("完成进度:"+DataUtil.percent(p.getCurrentLength(),p.getTotalLength()));
        jsonData.put("remain", (int)(p.getTotalLength()/v-time));
        jsonData.put("isStarted", true);
        jsonData.put("completed", p.isFlag());
        System.out.println("是否完成:"+p.isFlag());
        if (p.isFlag()){
            System.out.println("已完成,重置fileUploadProgress");
            ServletActionContext.getRequest().getSession().removeAttribute("fileUploadProgress");
        }
        setJsonData(jsonData);
        return SUCCESS;
    }

    public Map<String,Object> getJsonData() {
        return jsonData;
    }

    public void setJsonData(Map<String,Object> jsonData) {
        this.jsonData = jsonData;
    }
	
}
    
文件上传Action:
import java.io.File;    
import java.io.IOException;    
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.plat.pojo.video;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.struts2.ServletActionContext;  
import org.apache.struts2.dispatcher.*;

import com.opensymphony.xwork2.ActionSupport;
import com.plat.service.uploadVideoService;
import com.plat.utils.MyUUIDutils;
  

 
public class uploadVideoAction extends ActionSupport{   
      
         /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
		//上传文件存放路径   
           
         //上传文件   
         private File fileupload;   
         //上传文件名集合   
         private String fileuploadFileName;   
         //上传文件内容类型集合   
         private String fileuploadContentType;
         private String videoName;
         private String videoType;
         private String content;
         private String username;
		List<video> videos;
         public List<video> getVideos() {
			return videos;
		}

		public void setVideos(List<video> videos) {
			this.videos = videos;
		}

		public String getUsername() {
			return username;
		}

		public void setUsername(String username) {
			this.username = username;
		}

		public String getVideoName() {
			return videoName;
		}

		public String getVideoType() {
			return videoType;
		}

		public void setVideoType(String videoType) {
			this.videoType = videoType;
		}

		public String getContent() {
			return content;
		}

		public void setContent(String content) {
			this.content = content;
		}

		public void setVideoName(String videoName) {
			this.videoName = videoName;
		}

		public File getFileupload() {   
             return fileupload;   
         }   
  
         public void setFileupload(File fileupload) {   
             this.fileupload = fileupload;   
         }   
  
        public String getFileuploadFileName() {   
            return fileuploadFileName;   
        }   
  
         public void setFileuploadFileName(String fileuploadFileName) {   
             this.fileuploadFileName = fileuploadFileName;   
         }   
  
         public String getFileuploadContentType() {   
             return fileuploadContentType;   
         }   
  
         public void setFileuploadContentType(String fileuploadContentType) {   
             this.fileuploadContentType = fileuploadContentType;   
         }   
         uploadVideoService uploadVideoService;
         public uploadVideoService getUploadVideoService() {
			return uploadVideoService;
		}

		public void setUploadVideoService(uploadVideoService uploadVideoService) {
			this.uploadVideoService = uploadVideoService;
		}

		public String execute() throws Exception { 
				video video = new video();
				
				
		        try {  
		            //我们需要做的就是提供一个服务器的存放地址即可  
		            String realPath = ServletActionContext.getServletContext().getRealPath("/WEB-INF/upload");  
		            //判断路径是否存在,不存在创建 
		            String uuid = MyUUIDutils.getUUID();
					video.setContent(content);
					video.setVideoType(videoType);
					video.setUsername(username);
					video.setId(uuid);
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
					video.setUploadDate(sdf.format(new Date()).toString());
					video.setLink("/upload/"+uuid+fileuploadFileName);
		            File dir = new File(realPath);  
		            if (!dir.exists()) {  
		                dir.mkdirs();  
		            }
		            
		            video.setTitle(fileuploadFileName);
		            //第一个参数是文件 ,第二个参数是文件在服务器中的位置,fileUtils 是org.apache.commons.io.FileUtils提供好的现成的方法  
		            //FileUtils.copyFile(upload,new File(dir,uploadFileName));//copy文件,服务器中有备份文件  
		            FileUtils.moveFile(fileupload,new File(dir,uuid+fileuploadFileName));//剪切文件,推荐使用,无备份文件 
		            List<video> videos = uploadVideoService.save(video);
		            if (videos.isEmpty()) {
		            	return "error";
					}
		        } catch (IOException e) {  
		            e.printStackTrace();  
		              return "error";
		        } 
		        return "SUCCES";
		     	        
		}	
		}
这里需要配置一下Struts.xml:
<package name="json" extends="struts-default,json-default">
        <action name="loadBar" class="ProgressAction" method="execute">  <!-- 进度监察Action -->
            <result name="success" type="json">
                <param name="root">jsonData</param><!-- action中的要返回的属性 -->
            </result>
        </action>
        <action name="uploadAction" class="uploadVideoAction" method="execute">            <!-- 上传文件Action -->
    		<result name="SUCCESS" type="dispatcher">upload.jsp</result>
 		</action>
 </package>

到这里后端的准备工作基本就完成了,剩下的就是前端页面的编写了

我用的是bootstrap的进度条所以只用引入bootstrap.js就可以直接用了

<div class="progress">
    <div id="pros" class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width:0%;">
    </div>
</div>

控制进度条的代码:

在提交form的时候同步调用计时器setInterval

<form enctype="multipart/form-data"  action="uploadAction" method="post" οnsubmit="submitForm()">
<script type="text/javascript"> 
	function submitForm(){
		setInterval(progressBar,500);
	}
	function progressBar() {
		console.log("询问后台进度...");
		$.ajax({
			type : "GET", //提交方式
			url : "loadBar",//路径
			success : function(result) {//返回数据根据结果进行相应的处理
				console.log("result:"+result);
				console.log("文件是否上传完成" + result.completed);
				if (result.isStarted) {
					if (result.completed) {
						$(".progress").hide();
						clearInterval(progressBar);//清除计时器
					} else {
						$('#pros').width(result.percent);
						$('#pros').text(result.percent);
						$(".remain").text(result.remain);
					}
				} else {
					console.log("文件还没有提交");
							
				}
			},
			//异常处理
			error : function(XMLHttpRequest, textStatus, errorThrown) {
				console.log(XMLHttpRequest + "---" + textStatus + "---"
						+ errorThrown);
			}
		});

	}
</script>

好了,这就完成了!

参考自:https://blog.csdn.net/csu_passer/article/details/78246365





    
    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值