struts2实现文件上传进度条(前端JS+Java)(自我整理)

需要做一个文件上传进度的效果,结合网上资料和自己的实践后,这里做一个整理

步骤如下:

1.重写、自定义JakartaMultiPartRequest类

<span style="font-size:12px;">package com.hikvision.fileUploadProcess.interceptor;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest;

public class MyJakartaMultiPartRequest extends JakartaMultiPartRequest  {
    @Override
    public void parse(HttpServletRequest servletRequest, String saveDir)
            throws IOException {
            //什么也不做  

    }
}</span><strong style="font-size: 14px; ">
</strong>

原因:

struts2默认的拦截器中有一个FileUploadInterceptor,它会拦截所有的MultipartRequest,并且将得到的File及相关信息传递给action,因此在action被调用之前,文件上传已经被处理完了,不能引入监听文件写入时文件进度;

struts2处理文件上传使用的是commons-fileupload,因此我们可以使用ProgressListener。注意我们需要在解析请求的时候加入我们的监听器,我们首先想到的是替换掉FileUploadInterceptor,不幸的是 FileUploadInterceptor并不执行解析的任务,实际在FileUploadInterceptor被调用之前,MultipartRequest已经被解析了,文件上传的工作已经完成。而实际上对于所有的文件上传请求,struts2会为其生成一个MultiPartRequestWrapper进行包装,而它维护着一个
MultiPartRequest接口的实例。MultiPartRequest的实现类只有一个 JakartaMultiPartRequest,JakartaMultiPartRequest有一个方法parseRequest,此方法负责解析 request并生成FileItem,即对文件进行读写操作,因此我们可以重写此方法,添加ProgressListener。不幸的是,JakartaMultiPartRequest的很多方法都是private的,我们不能继承它然后重写parseRequest方法,JakartaMultiPartRequest实现了MultiPartRequest接口,我们可以编写一个类,实现
MultiPartRequest接口,替代JakartaMultiPartRequest类的代码全都拷贝过来,并修改parseRequest方法,完成文件的写入与进度的监听。

2.配置struts2.xml

<!-- 1配置自定义文件类myRequestParser,继承MultiPartRequest重写 -->
	<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
		name="myRequestParser" class="com.hikvision.fileUploadProcess.interceptor.MyJakartaMultiPartRequest"
		scope="default" optional="true" />

	<!-- 注意struts2.3.15.1以前版本这里为struts.multipart.handler, struts2.3.15.1(包含2.3.15.1)这里为struts.multipart.parser-->
	<constant name="struts.multipart.parser" value="myRequestParser" /> 

	<!-- 配置项目所上传文件的最大的Size为1000M -->
	<constant name="struts.multipart.maxSize" value="1048576000"/> 

3.定义文件上传进度信息的类

package com.hikvision.fileUploadProcess.entity;

/**
 * 上传文件进度信息
 *
 * @author wanglei
 * @version 0.1
 */
public class FileUploadProgress {
	// 文件总长度(设置至少为1字节防止前台出现/0的情况)
	private long length = 1;
	// 已上传的文件长度
	private long currentLength = 0;
	// 上传是否完成
	private boolean isComplete = false;
	public long getLength() {
		return length;
	}
	public void setLength(long length) {
		this.length = length;
	}
	public long getCurrentLength() {
		return currentLength;
	}
	public void setCurrentLength(long currentLength) {
		this.currentLength = currentLength;
	}
	public boolean isComplete() {
		return isComplete;
	}
	public void setComplete(boolean isComplete) {
		this.isComplete = isComplete;
	}

	public FileUploadProgress() {
		super();
	}

}

4.实现ProgressListener接口

package com.hikvision.fileUploadProcess.impl;

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

import org.apache.commons.fileupload.ProgressListener;

import com.hikvision.fileUploadProcess.entity.FileUploadProgress;

/**
 * 文件上传进度消息
 * @author hongchenjin
 *
 */
public class FileUploadListener implements ProgressListener {
	private HttpSession session;

	public FileUploadListener(HttpServletRequest request) {
		session = request.getSession();
		FileUploadProgress fileUploadProgress = new FileUploadProgress();
		fileUploadProgress.setComplete(false);
		session.setAttribute("fileUploadProgress", fileUploadProgress);
	}

	//更新进度情况
	@Override
	public void update(long readedBytes, long totalBytes, int currentItem) {
		//实现文件上传的核心方法
		Object attribute = session.getAttribute("fileUploadProgress");
		FileUploadProgress fileUploadProgress  = null;
		if(null == attribute){
			fileUploadProgress = new FileUploadProgress();
			fileUploadProgress.setComplete(false);
			session.setAttribute("fileUploadProgress", fileUploadProgress);
		}else{
			 fileUploadProgress = (FileUploadProgress)attribute;
		}

		fileUploadProgress.setCurrentLength(readedBytes);
		fileUploadProgress.setLength(totalBytes);
		if(readedBytes==totalBytes){
			fileUploadProgress.setComplete(true);
		}else{
			fileUploadProgress.setComplete(false);
		}

		session.setAttribute("progress", fileUploadProgress);
	}

}

5.文件上传进度的action

package com.hikvision.modules.guide.action;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.hikvision.fileUploadProcess.entity.FileUploadProgress;
import com.hikvision.frame.entity.OperateResult;
import com.hikvision.modules.guide.entity.NameToLocalFile;
import com.hikvision.modules.guide.service.GuideService;
import com.hikvision.modules.guide.util.GetSharePathXml;
import com.hikvision.util.AjaxUtil;
import com.opensymphony.xwork2.ActionSupport;

public class GuideUploadAction extends ActionSupport {

	private GuideService guideService;

	public GuideService getGuideService() {
		return guideService;
	}

	public void setGuideService(GuideService guideService) {
		this.guideService = guideService;
	}

	//文件格式不支持
	public void typeNotSupport(){
		OperateResult result = new OperateResult(false,"");
		result.setResult(false);
		result.setMsg("上传文件最大不能超过100M;支持的格式为exe,png,jpg,gif,bmp,doc,docx,xls,rar,txt,zip,js,css,msi,pptx");
		AjaxUtil.ajaxWrite(result);
	}

	/**
     * 上传文件
     *
     * @return
     */
    public void uploadfile() {
    	OperateResult result = new OperateResult(false,"");
        try {
        	HttpServletRequest request = ServletActionContext.getRequest();
        	//获取文件备注
        	String comments = request.getParameter("comments");
        	//文件上传
            UploadFile.upload(request, ServletActionContext.getResponse());
            //将文件名和文件的对应关系存进数据库里
			NameToLocalFile nameToLocalFile = new NameToLocalFile();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			String time = sdf.format(new Date());
			nameToLocalFile.setCreatetime(time);
			//保存在服务器上的路径
			nameToLocalFile.setLocalpath("/" +  request.getParameter("variety") + "/" + request.getParameter("name"));
			nameToLocalFile.setName(request.getParameter("name"));
			nameToLocalFile.setVariety(request.getParameter("variety"));
			nameToLocalFile.setComments(comments);
			guideService.saveOrUpdate(nameToLocalFile);
            result.setResult(true);
            result.setMsg("上传成功");
        } catch (IOException e) {
            LOG.error("上传文件发生异常,错误原因 : " + e.getMessage());
            result.setMsg("上传文件最大不能超过100M;");
            result.setResult(false);
        }
        AjaxUtil.ajaxWrite(result);
    }

    /**
     * 修改文件
     */
    public void updateNameToLocalFile(){
    	OperateResult result = new OperateResult(false,"");
    	HttpServletRequest request = ServletActionContext.getRequest();
    	//种类
    	String variety = request.getParameter("variety");
    	//名称
		String name = request.getParameter("name");
		//文件备注
    	String comments = request.getParameter("comments");
		//是否上传了文件
		Boolean flag = Boolean.parseBoolean(request.getParameter("flag"));
		//id
		int id = Integer.parseInt(request.getParameterValues("ids")[0]);
		//根据id获取数据库的nameToLocalFileById
		NameToLocalFile nameToLocalFileById = guideService.getNameToLocalFileById(id);
		//分为两种情况,第一种为用户重新上传了文件,第二种是用户只修改了名字和种类
		if(flag){
			/**
			 * 用户重新上传文件的情况
			 */
			//删除原来文件
			String localpath = nameToLocalFileById.getLocalpath();
			String realPath = GetSharePathXml.getShareFolderPath() + localpath;
			File file = new File(realPath);
			//用户上传了文件
			try { 

				if(file.exists()){
					//删除原来文件(判断是否存在该文件,存在就删除)
					file.delete();
				}

				//文件上传
	            UploadFile.upload(request, ServletActionContext.getResponse());

				result.setResult(true);
				result.setMsg("修改成功");
			} catch (Exception e) {
				result.setResult(false);
				result.setMsg("修改失败");
			}
		}
		//将文件名和文件的对应关系存进数据库里
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String time = sdf.format(new Date());
		nameToLocalFileById.setCreatetime(time);
		if(flag){
			//保存在服务器上的路径
			nameToLocalFileById.setLocalpath("/" +  variety + "/" + name);
			nameToLocalFileById.setName(name);
		}
		nameToLocalFileById.setVariety(variety);
		nameToLocalFileById.setComments(comments);
		guideService.saveOrUpdate(nameToLocalFileById);
		result.setResult(true);
		result.setMsg("修改成功");
		AjaxUtil.ajaxWrite(result);

    }
    /**
     * 显示上传文件进度进度
     *
     * @return page view
     */
    public void progress() {
        // 新建当前上传文件的进度信息对象
        FileUploadProgress p = null;
        Object attribute = ServletActionContext.getRequest().getSession().getAttribute("fileUploadProgress");
        if(null == attribute){
        	p = new FileUploadProgress();
        	 // 缓存progress对象
            ServletActionContext.getRequest().getSession().setAttribute("fileUploadProgress", p);
        }else{
        	p = (FileUploadProgress)attribute;
        }

        ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");
        ServletActionContext.getResponse().setHeader("pragma", "no-cache");
        ServletActionContext.getResponse().setHeader("cache-control", "no-cache");
        ServletActionContext.getResponse().setHeader("expires", "0");
        //以下方法为输出json(封装,可根据实际情况修改输出的方式)
        AjaxUtil.ajaxWriteObject(p);
    }

    /**
     * 清除session
     */
    public void clearProgressSession(){
    	ServletActionContext.getRequest().getSession().setAttribute("fileUploadProgress", null);
    }
}

6.UploadFile类(文件上传)

package com.hikvision.modules.guide.action;

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;

import com.hikvision.fileUploadProcess.impl.FileUploadListener;
import com.hikvision.modules.guide.util.GetSharePathXml;
/**
 * 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 {
        if (request.getContentType() == null) {
            throw new IOException(
                    "the request doesn't contain a multipart/form-data stream");
        }

        // 上传临时路径
        String path = GetSharePathXml.getShareFolderPath();
        // 设置上传工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setRepository(new File(path));
        // 阀值,超过这个值才会写到临时目录
        factory.setSizeThreshold(1024 * 1024 * 10);
        ServletFileUpload upload = new ServletFileUpload(factory);
        // 最大上传限制
        upload.setSizeMax(1024 * 1024 * 1000);
        // 设置监听器监听上传进度
        upload.setProgressListener(new FileUploadListener(request));
        try {
            List<FileItem> items = upload.parseRequest(request);

            //获取文件类型
            String variety = request.getParameter("variety");
            for (FileItem item : items) {

                // 非表单域
                if (!item.isFormField()) {
                    FileOutputStream fos = new FileOutputStream(path + "/"  + variety + "/" + item.getName());
                    // 文件全在内存中
                    if (item.isInMemory()) {
                        fos.write(item.get());
                    } 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("删除临时文件!");

                    LOG.info("更新progress对象状态为完成状态!");
                }
            }
        } catch (Exception e) {
            LOG.error("上传文件出现异常, 错误原因 : " + e.getMessage());

            request.getSession().removeAttribute("percent");
        }
    }

}

前台部分:点击上传,然后循环调用

//进度条显示
	var everylisten = function() {
		//显示进度条
		$("#prosbar").parent("div").css({"display":"block"});
		$.ajax({
			url : 'http://127.0.0.1/guideUpload!progress.action',
			method : 'GET',
			timeout : 120000,
			contentType : "application/json; charset=utf-8",
			dataType : "json",
			success : function(result) {
				if(null != result) {
						if(result.complete) {
							//将进度条长度设为0并隐藏
							$("#prosbar").css({"width":"0%"});
							clearTimeout(everylisten);
							//清除session
							clearProgressSession();
						}else{
							var width = result.currentLength * 100 / result.length + "%";
							$("#prosbar").css({"width": width});
							setTimeout(everylisten, 500);
						}
				}else{
					alert(data.msg);
				}
			}
		});
	};   

清除进度条session

//清除session
	function clearProgressSession(){
		$.ajax({
			url : hik.guide.getContextPath() + '/guideUpload!clearProgressSession.action',
			method : 'GET',
			timeout : 120000,
			contentType : "application/json; charset=utf-8",
			dataType : "json",
			success : function(result) {

			}
		});
	}  

点击文件上传时的js代码(PS:文件上传时相关参数写在路径里,不然后台接收不到(如果不写在路径里,测试时在浏览器调试发现参数确实传了,但在request里这个参数的值为空),因为请求地址是要经过tomcat的,为防止中文乱码的情况,在tomcat路径conf文件夹下找到server.xml文件,找到以下项,添加红色部分的代码 <Connector
URIEncoding="UTF-8" connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>
,保存后重启tomcat)

$("#GuideForm").submit(function(){
					everylisten();
					return false;
					$.ajaxFileUpload
					(
						{
							url:'http://127.0.0.1/guideUpload!uploadfile.action?'
							    + $("#GuideForm").serialize(),
							secureuri:false,
							fileElementId:'upload',
							dataType: 'json',
							data:{},
							success: function (data, status)
							{
								$(dialogEl).dialog('close');
								//上传成功后,提示用户上传成功
								if(data.success){
									alert("success");
								}else{
									alert("false");
								}
							},
							error: function (data, status, e)
							{
								alert("出错了");
							}
						}
					)
				});

页面代码(红色部分为必须写的地方):

<span style="color:#333333;"><form id="GuideForm" name="guideForm" action=""
	onsubmit="return false;"
	class="form-horizontal five-columns character5 padding-top8px"
	</span><span style="color:#cc0000;">enctype="multipart/form-data"</span><span style="color:#333333;"> method="post">  

	<div>
		<input type="hidden" name="ids" >
		<div class="control-group five-columns">
	        <label class="control-label">文件名称:</label>
	        <div class="controls">
	          <input class="span4" type="text" name="name" maxlength="20" readonly="readonly"/>
	        </div>
     	 </div>
     	<div class="control-group five-columns">
			<label class="control-label">文件类型:</label>
			<div class="controls">
				<select name="variety">
					<option value="tools">开发工具</option>
					<option value="ecliplse_plugin">Eclipse常用插件</option>
					<option value="svn">代码版本控制SVN</option>
					<option value="database">数据库</option>
					<option value="other">其他</option>
				</select>
			</div>
		</div>
		<div class="control-group five-columns" style="display:none;">
			<label class="control-label">文件路径:</label>
	        <div class="controls">
	          <a name="path" style="color:blue"></a>
	        </div>
	        <div class="controls">
	          <input type="button" class="btn btn-primary uploadReset" value="重新上传" name="uploadReset">
	        </div>
		</div>
		<div class="control-group five-columns">
			<div class="controls">
			<label class="control-label">上传文件 :</label>
			<input class="span4" type="file"
				name="upload" maxlength="20" id="upload" />
			</div>
		</div>
		<div class="control-group five-columns">
			<div class="controls">
			<label class="control-label">文件备注:</label>
				<textarea rows="" cols="" name="comments" maxLength="50"></textarea>
			</div>
		</div>
		<div class="progress progress-striped active" >
  			<div class="bar" style="width: 0%;" id="prosbar"></div>
		</div>
	</div>	 

	<!-- 上传进度条 -->
</form></span>

时间: 2024-04-23 09:29:37

struts2实现文件上传进度条(前端JS+Java)(自我整理)的相关文章

Struts2 文件上传 进度条显示

参考成功博客:http://blog.sina.com.cn/s/blog_bca9d7e80101bkko.html 待测试博客:http://blog.csdn.net/z69183787/article/details/52536255 Struts2 文件上传 进度条显示

基于HT for Web矢量实现HTML5文件上传进度条

在HTML中,在文件上传的过程中,很多情况都是没有任何的提示,这在体验上很不好,用户都不知道到时有没有在上传.上传成功了没有,所以今天给大家介绍的内容是通过HT for Web矢量来实现HTML5文件上传进度条,矢量在<矢量Chart图表嵌入HTML5网络拓扑图的应用>一文中已经讲述了关于setCompType()方法的应用,今天我们用setImage()方法充分利用系统中定义好的矢量资源来实现文件上传进度条,我们先来看下效果图: 从效果图可以看到,向服务器上传了一个mp4文件,并在最下方显示

JQuery和Servlet实现文件上传进度条,能显示上传速度,上传的百分比等

原文:JQuery和Servlet实现文件上传进度条,能显示上传速度,上传的百分比等 源代码下载地址:http://www.zuidaima.com/share/1550463319542784.htm JQuery和Servlet实现文件上传进度条,能显示上传速度,上传的百分比等

Layui多文件上传进度条

Layui原生upload模块不支持文件上传进度条显示,百度,谷歌找了一下不太适用.后面找到一个别人修改好的JS,替换上去,修改一下页面显示即可使用,一下是部分代码 HTML: <div class="layui-upload"> <button type="button" class="layui-btn layui-btn-normal" id="fileList">选择多文件</button

spring定时任务-文件上传进度条

spring定时任务 导依赖 <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz --> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </depen

ajax文件上传进度条

写在前面: 思路:首先将表单提交servlet,servlet中做文件上传处理,上传的参数封装成对象存入session中,提交到的页面为隐藏的iframe窗口.然后使用ajax异步请求获取session中的对象,并将对象转换成json对象输出出来.当对象状态为上传完成或操作异常时将session中对应的属性清除掉.异步操作的回调函数可以使用var jinduStatus = eval("("+xmlHttp.responseText+")") 的方法将json转换为

实现一个简单的文件上传进度条

新手入门web 文件上传完成 取得的进展 没有进度条只能用文字 不好看  必须是一个进度条  没有艺术 互联网很 进度条 需要图片 有多种帧的 他看上去好麻烦 让自己的单纯 很简单 我没想到这么复杂  共享 jsp页面 <tr> <td width="100">图片</td> <td> <div style="width: 450px;"> <div class="file-box"

使用html5实现文件上传进度条

html <div id="file"> <input type="file" name="ver" id="ver"/> <font color="red">*(apk,ipa目前为自动重命名)</font><br /> <div class="progress"><span class="bgpr

layui文件上传进度条(模拟)

1.修改上传组件js(没测) https://blog.csdn.net/weixin_42457316/article/details/81017471 https://www.cnblogs.com/youmingkuang/p/9183528.html https://fly.layui.com/jie/19430/ 1.upload.js 扩展 功能利用ajax的xhr属性实现该功能修改过modules中的upload.js文件功能具体实现:在js文件中添加监听函数 //创建监听函数 v