struts2+AJAX文件上传进度条的基本实现

10 篇文章 0 订阅
5 篇文章 0 订阅

    最近想要用struts2来实现文件上传进度条,结合自己所学的知识和网上找到的一些资料,现在整理好了,以供各位网友作为参考,也给自己多屯点干货。

    要实现文件上传的进度条的现实,关键就是要获取当前文件的上传状态,知道当前上传的是哪个文件,文件的总大小以及上传了多少。以前,学习apache fileupload框架时,可以在文件上传的时候添加一个文件上传进度的监听器,下面贴出官网给出的示例,相信有一定基础的童靴一看基本上就懂了。

//Create a progress listener
ProgressListener progressListener = new ProgressListener(){
   public void update(long pBytesRead, long pContentLength, int pItems) {
       System.out.println("We are currently reading item " + pItems);
       if (pContentLength == -1) {
           System.out.println("So far, " + pBytesRead + " bytes have been read.");
       } else {
           System.out.println("So far, " + pBytesRead + " of " + pContentLength
                              + " bytes have been read.");
       }
   }
};
upload.setProgressListener(progressListener);
   上面的ProgressListener接口有一个update()方法,在上传文件的时候会自动的调用这个方法,把相应的状态传递过来,参数pBytesRead就是当前读取的字节数,pContentLength文件的总大小,pItems当前上传的是第几个文件。了解了上面的代码后,你应该大致知道该怎么实现了吧。

   但是在struts2中,上传的文件直接是保存到action里面的,并用一个File对象来接受,我们并不需要干涉文件上传的过程,我们只知道那个上传的文件是直接可以获取到的,例如下面写的这段代码:

       private File file;
	
	private String contentType;
	
	private String fileName;
	
	public void setUpload(File file){
		this.file = file;
	}
	
	public void setUploadContentType(String contentType){
		this.contentType = contentType;
	}
	
	public void setUploadFileName(String fileName){
		this.fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
	}

此时上传的文件已经是一个完整的文件,你能获取到它的文件类型已经文件名称。它以临时文件的方式保存在硬盘上,我们要做的只是把这个文件放到我们想要放到的目录。但是我们怎么样来添加哪个监听器呢?仔细阅读struts2的源码,可以发现如下的代码

 public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
        // don't wrap more than once
        if (request instanceof StrutsRequestWrapper) {
            return request;
        }

        String content_type = request.getContentType();
        if (content_type != null && content_type.contains("multipart/form-data")) {
            MultiPartRequest mpr = getMultiPartRequest();
            LocaleProvider provider = getContainer().getInstance(LocaleProvider.class);
            request = new MultiPartRequestWrapper(mpr, request, getSaveDir(servletContext), provider);
        } else {
            request = new StrutsRequestWrapper(request, disableRequestAttributeValueStackLookup);
        }

        return request;
    }

这个方法是Dispatcher类的方法(具体的东西大家可以去追源代码,从StrutsPrepareAndExecuteFilter.doFilter()方法里面的 request = prepare.wrapRequest(request);这段话开始),如果是文件上传request被包装成了 MultiPartRequestWrapper。

我们都知道,struts2的文件上传是以拦截的方式实现的,即FileUploadInterceptor拦截器,会调用拦截器的intercept方法,仔细的阅读intercept里面的这段方法:

MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;

        if (multiWrapper.hasErrors()) {
            for (String error : multiWrapper.getErrors()) {
                if (validation != null) {
                    validation.addActionError(error);
                }
            }
        }

        // bind allowed Files
        Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
        while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
            // get the value of this input tag
            String inputName = (String) fileParameterNames.nextElement();

            // get the content type
            String[] contentType = multiWrapper.getContentTypes(inputName);

            if (isNonEmpty(contentType)) {
                // get the name of the file from the input tag
                String[] fileName = multiWrapper.getFileNames(inputName);

                if (isNonEmpty(fileName)) {
                    // get a File object for the uploaded File
                    File[] files = multiWrapper.getFiles(inputName);
                    if (files != null && files.length > 0) {
                        List<File> acceptedFiles = new ArrayList<File>(files.length);
                        List<String> acceptedContentTypes = new ArrayList<String>(files.length);
                        List<String> acceptedFileNames = new ArrayList<String>(files.length);
                        String contentTypeName = inputName + "ContentType";
                        String fileNameName = inputName + "FileName";

                        for (int index = 0; index < files.length; index++) {
                            if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation)) {
                                acceptedFiles.add(files[index]);
                                acceptedContentTypes.add(contentType[index]);
                                acceptedFileNames.add(fileName[index]);
                            }
                        }

                        if (!acceptedFiles.isEmpty()) {
                            Map<String, Object> params = ac.getParameters();

                            params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
                            params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
                            params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
                        }
                    }
                } else {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn(getTextMessage(action, "struts.messages.invalid.file", new String[]{inputName}));
                    }
                }
            } else {
                if (LOG.isWarnEnabled()) {
                    LOG.warn(getTextMessage(action, "struts.messages.invalid.content.type", new String[]{inputName}));
                }
            }
        }
我们再来仔细的看下这个类,可以发现在这个类的构造器中,有这样一个接口MultiPartRequest,它的实现类是JakartaMultiPartRequest,没错就是这个类,用来处理上传请求的,然后您可以看到这个类中的
 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));
    }
我们所要做的工作就是在这个方法中添加一个ProgressListener, 因此我们需要对这个方法重新,改写后的这个方法如下:
 private List<FileItem> parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
	        DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
	        ServletFileUpload upload = new ServletFileUpload(fac);
	        upload.setSizeMax(maxSize);
	        FileUploadProgressListener progressListener = new FileUploadProgressListener(servletRequest);
	        upload.setProgressListener(progressListener);
	        return upload.parseRequest(createRequestContext(servletRequest));
	    }

一切都好像差不多了,但是不要忘记把这个文件上传解析器给配置进来,

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="progress" class="com.warnow.action.fileupload.ProgressMultiPartRequest" scope="default"/>
<constant name="struts.multipart.parser" value="progress" />

这个解析器在struts-default.xml文件中是有配置的如下:

<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default"/>
文件上传的jsp页面如下所示:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>testUpload progress!</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">
	<script type="text/javascript" src="jquery-1.6.4.js"></script>
  </head>
  
  <body>
    <form action="upload.action"  enctype="multipart/form-data" method="post">
    	<input type="file" name="upload">
    	<input  type="submit" value="submit" οnclick="formSubmit()">
    </form>
    
    <span id="percent"></span>
    <div style="width: 560px;height: 25px;background-color: rgb(193, 210, 240);">
    	<div id="progress" style="background-color: blue;height: 25px;width:0%"></div>
    </div>
 	
    <script type="text/javascript">
    	function formSubmit(){
    		window.setInterval("getUploadStatus()", 1000);
    		document.forms[0].submit();
    	}
    	
    	function getUploadStatus(){
    		 $.post("fileUploadStatus.action",
    				 function(data){
    				      $("#percent").html("文件已经上传:" + data);
    				      $("#progress").css("width", data);
    		});
    	}
    </script>
  </body>
</html>

效果如图:


还有一些文件未一一列出出来,现在给出源代码的链接项目源代码)——供大家下载学习,有什么不懂的地方,欢迎随时的问我。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值