`
mj4d
  • 浏览: 302890 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

struts2 上传及进度条显示

阅读更多

1、struts2上传

以下是一个上传涉及的代码,从view到action的各个阶段代码:

页面:

<form action="../upload/upload.action" id="exForm" method="post" enctype="multipart/form-data" >
        <ul>
            <li>
                <input type="file" name="uploadFile" size="20"/>
                <input type="submit" value="导入"/>
            </li>
        </ul>
</form>

 

 action代码:

public class UploadFileAction extends ActionSupport {

    private static final long serialVersionUID = 5563083429360573304L;
    /** 上传文件 */
    private File                uploadFile;
    private String            uploadFileFileName;
    private String            uploadFileContentType;

    public String upload() {
        try {
            //这里是上传文件,可做具体处理
            IOUtils.copy(new FileInputStream(uploadFile), new FileOutputStream(new File("C:\\" + uploadFileFileName)));
            System.out.println(uploadFileFileName);
            System.out.println(uploadFileContentType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SUCCESS;
    }
}

 

 配置文件就不再描述。以上就是在struts2中上传涉及的代码,同时还可以支持同时上传多个文件:

支持同时上传多个文件:

<form action="../upload/upload.action" id="exForm" method="post" enctype="multipart/form-data" >
        <ul>
            <li>
                <input type="file" name="uploadFiles" size="20"/>
		<input type="file" name="uploadFiles" size="20"/>
		<input type="file" name="uploadFiles" size="20"/>
                <input type="submit" value="导入"/>
		<input type="input" name="message"/>
            </li>
        </ul>
</form>

和action代码:

public class UploadFileAction extends ActionSupport {

    private static final long serialVersionUID = 5563083429360573304L;
    /** 上传文件 */
    private File[]            uploadFiles;
    private String[]          uploadFilesFileName;
    private String[]          uploadFilesContentType;

    public String upload() {
        try {
            int index = 0;
            for (File file : uploadFiles) {
                IOUtils.copy(new FileInputStream(file), new FileOutputStream(new File("C:\\"
                        + uploadFilesFileName[index])));
                System.out.println(uploadFilesFileName[index]);
                System.out.println(uploadFilesContentType[index]);
                index++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SUCCESS;
    }}

 

 

2、几点说明

1、在上面上传过程中,页面file域属性名与action中File保持一致。如上:

name="uploadFile" 
和
private File            uploadFile

多个文件需要是数组。

 

2、之所以如此简单,得益于struts2中默认package:struts-default中

<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>

 在FileUploadInterceptor中讲HttpServletRequest请求对象封装成MultiPartRequestWrapper,对上传文件提供了对上传文件的各种处理:

这里提供了对文件、文件名、contentType等属性获取的封装,当然也有对普通表单字段的封装,即如果在上传的表单中有非file域也统一可以获取,而这在普通的servlet上传中并不能简单的处理,如上面的多个文件上传表单中的message,只需要在action中有相应的getter/setter即可获取这些属性。而完成这一切的是一个叫MultiPartRequest的家伙。

 

3、MultiPartRequest

这是上传拦截器中处理封装的具体类,这涉及struts2中上传的底层具体实现,在这个接口中,我们能看到struts2中提供了一个默认的实现:

public class JakartaMultiPartRequest implements MultiPartRequest

在struts2的default.properties中解析有如下说明:

### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser=jakarta
# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
struts.multipart.maxSize=2097152

这里对MIME-type为multipart/form-data的几种支持,而默认为jakarta,即在使用struts2的上传,需要添加相应的依赖(版本自行控制):

		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.2.1</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>1.3.2</version>
		</dependency>
  

4、关于file、filename、contentType

前面已经说了,在action中的File需要和也没file域中的名字保持一致,如果多个则是File数组。而如果要获取fileName以及相应的contentType,命名也有一定的限制,如上面的action中:

    private File[]            uploadFiles;
    private String[]          uploadFilesFileName;
    private String[]          uploadFilesContentType;

 而这里的命名来自FileUploadInterceptor中对MultiPartRequestWrapper解析完放置于ActionContext中所作的处理:

见MultiPartRequestWrapper中:

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, ac.getLocale())) {
                                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()]));
                        }
                    }

 

5、上传进度条显示

在上面第三点已经说明,在struts2中,默认的实现是JakartaMultiPartRequest,这是基于common-fileupload的实现。要处理上传进度条,在common-fileupload中有提供监听上传进度的接口:

/**
 * The {@link ProgressListener} may be used to display a progress bar
 * or do stuff like that.
 */
public interface ProgressListener {
    /** Updates the listeners status information.
     * @param pBytesRead The total number of bytes, which have been read
     *   so far.
     * @param pContentLength The total number of bytes, which are being
     *   read. May be -1, if this number is unknown.
     * @param pItems The number of the field, which is currently being
     *   read. (0 = no item so far, 1 = first item is being read, ...)
     */
    void update(long pBytesRead, long pContentLength, int pItems);
}

 根据在网上找到的一些资料,这里做了一个实现。首先需要实现该接口,获取显示的进度,一般我们按照百分比来计算,可以在实现的处理监听过程中将该值写入struts2的ActionContent中:

public class ResourceProgressListener implements ProgressListener {

    public ResourceProgressListener(HttpServletRequest request) {
    }

    public void update(long readedBytes, long totalBytes, int currentItem) {
        String process = readedBytes * 1.0 / totalBytes * 100 + "";
        ActionContext.getContext().getSession().put("currentUploadStatus", process);
    }

}

 接下来需要替换掉struts2中默认的实现,并在自己的实现中将该监听接口注册进去。在struts2-core-2.2.1.jar这个版本中,找到默认实现类JakartaMultiPartRequest,我们可以将代码全部复制过来,在这个版本的处理中,我们可以看到直接将上传请求用common-fileupload处理是在方法parseRequest中。比如我们将自己的实现叫MultiPartProcessRequest,代码将默认实现JakartaMultiPartRequest中拷贝过来,替换下面的方法:

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

        //--------------begin add process Listener-----------------//
        ResourceProgressListener progressListener = new ResourceProgressListener(servletRequest);//新建一个监听器
        upload.setProgressListener(progressListener);//添加自己的监听器
        //-------------- end add process Listener-----------------//

        return upload.parseRequest(createRequestContext(servletRequest));
    }

 上面注释部分是对默认实现的修改,增加了监听。下面需要在struts2中修改默认配置为当前自己的实现,一般我们将该参数配置在struts.xml:

	<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" 
		name="requestParser" class="com.sa.web.upload.MultiPartProcessRequest" scope="default" optional="true" />
	<constant name="struts.multipart.handler" value="requestParser" />

 到此上传进度监听就处理完成,接下来需要处理在页面的实现:在提交上传的form表单后,将定时调用Ajax请求去读取ActionContext中的进度信息,并在页面显示该实时进度。这里需要在上传的Action中新增一个action方法,读取实时进度,并Ajax返回,都是一些常规操作:

UploadFileAction:

    /**
     * Ajax get current process info
     * @return
     * @author Administrator
     * @date 2012-6-3
     */
    public String process() {
        process = (String) ActionContext.getContext().getSession().get("currentUploadStatus");
        return SUCCESS;
    }

 在struts-upload.xml中返回json:

		<!-- process -->
		<action name="process" class="com.sa.web.upload.UploadFileAction" method="process">
			<result name="success" type="json">
				<param name="ignoreHierarchy">true</param>
				<param name="excludeNullProperties">true</param>
				<param name="root">process</param>
			</result>			
		</action> 

 接下来,就是在页面如何显示。这里做得很粗糙,只是将Ajax读取的数据展现。这里用到了javascript的定时函数setInterval。但是有个问题,在js中提交form表单中会阻塞该页面请求进程,就不会去请求setInterval中的方法。这里用到了jquery.form.js来异步提交表单,在提交表单后去定时获取后台进度信息,并在页面显示。同时,在表单提交完成后需要停止该定时任务。

<script type="text/javascript" src="../resources/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../resources/js/jquery.form.js"></script>
<script type="text/javascript">
$(function () {

	//这个是为了在上传完成后停止该定时任务,或者有更好的办法?
	window.processBar = function(){return setInterval(function(){
                                                		if(isExNew){
                                                    			jQuery.ajax({
                                                            		type: "POST",
                                                            		cache: false,
                                                            		url: "http://localhost:8080/sa-web/upload/process.action",
                                                            		data: {},
                                                            		dataType: "json",
                                                            		success: function (data) {$("#processId").append(data).append(",");}
                                                        		})
								}
                                                	}, 1000);
	};
	
	//异步提交Form表单,在ajaxForm回调函数中去实时查询最新进度
    window.fnExNew = function () {
		window.isExNew = true;
		$('#exForm').ajaxForm(function(){setInterval(function(){
                                                		if(isExNew){
                                                    			jQuery.ajax({
                                                            		type: "POST",
                                                            		cache: false,
                                                            		url: "http://localhost:8080/sa-web/upload/process.action",
                                                            		data: {},
                                                            		dataType: "json",
                                                            		success: function (data) {$("#processId").append(data).append(",");}
                                                        		})
								}
                                                	}, 1000)}); 
    };
	
    //上传完成的回调方法,
    window.fnEx = function (p) {
    	if(isExNew){
    		alert("提示", "上传完成");
    	}else{
        	alert("提示", p);
    	}
		window.isExNew = false;
		clearInterval(processBar);
    };
});
</script>

 至于回调函数fnEx是在UploadFileAction中upload上传完成处理后返回一个页面,只有一句话那就是调用该方法:

<script>
try{
parent.fnEx("$!message");
}
catch(e){}
</script>

 到此为止整个简单的展现处理已经完成,当然在实际生产中这样的展现可不行,需要显示进度条可在ajaxForm提交的回调中弹出DIV调用一些jquery组件直观显示,这是后话不表

 

分享到:
评论
3 楼 anybyb 2013-07-26  
请教一个问题:我按照您的这么做,最后实验的时候发现,得到的process 是空值
我去自己实现的那个监听器中的update方法里面打出一句话,可是更本没有输出,配置文件我也配置了的呀!!
2 楼 bugci 2013-03-07  
No mapping found for dependency [type=com.opensymphony.xwork2.LocaleProvider, name='default'] in public void com.tss.util.MultiPartProcessRequest.setLocaleProvider(com.opensymphony.xwork2.LocaleProvider).

按照文章配置,报错了
1 楼 jackyrong 2012-08-22  
HI,能否提供完整工程下载学习呢?谢谢,jackyrong@tom.com

相关推荐

    struts2上传文件进度条显示

    总的来说,Struts2实现文件上传进度条显示需要整合服务器端的进度回调和客户端的进度更新,确保数据的实时同步。同时,为了提高用户体验,应考虑优化大文件上传的性能,如分块上传、断点续传等技术。通过以上步骤,...

    java struts2实现文件上传进度条显示

    在Java Struts2框架中实现文件上传进度条显示,主要涉及到的技术点包括Struts2的文件上传、Ajax异步通信以及前端进度条组件的使用。下面将详细讲解这些知识点。 首先,Struts2的文件上传功能是通过Struts2提供的`...

    struts2_uploadify带进度条的多文件上传下载

    总之,这个项目实例为使用Struts2和Uploadify实现带进度条的多文件上传及下载功能提供了一个基础模板,对于学习和实践此类功能的开发者来说是一个有价值的参考。通过深入研究和理解这个项目的代码,可以提升对Struts...

    struts2实现上传进度条显示

    在Struts2中实现文件上传进度条显示,主要是通过Ajax技术、监听器和JavaScript来完成的。以下是对这个功能的详细解释: 1. **原理**: - **Ajax**(异步JavaScript和XML)技术允许在不重新加载整个网页的情况下,...

    Struts2文件上传进度条

    Struts2文件上传进度条是Web开发中一个实用的功能,它允许用户在文件上传过程中查看当前的上传进度,提供更好的用户体验。在这个项目中,我们利用Struts2框架的拦截器机制来实现这一功能。 首先,我们需要理解...

    struts1上传文件带进度条

    2. **后端处理**:在Struts1的Action中,我们需要自定义一个ActionForm,扩展`org.apache.struts.action.ActionForm`,并重写`execute()`方法来处理文件上传。在这个方法里,可以使用`FormFile`对象获取文件,并将其...

    struts2+ajax文件进度条的实现

    在Struts2中实现文件上传功能,通常会涉及到处理大文件、用户体验优化等问题,如显示文件上传进度条。这个场景下,我们结合Ajax技术,可以创建一个实时反馈文件上传进度的动态界面,提升用户交互体验。 首先,我们...

    Struts2文件上传进度条显示

    参考文章地址: http://blog.csdn.net/garryyrc/article/details/5499113 http://www.telio.be/blog/2006/01/06/ajax-upload-progress-monitor-for-commons-fileupload-example

    Struts2+上传进度条完美运行

    在这个“Struts2+上传进度条完美运行”的主题中,我们将深入探讨如何在Struts2框架下实现文件上传功能,并结合进度条展示上传进度,提供用户友好的交互体验。 1. **Struts2文件上传**: Struts2通过`struts2-core`...

    struts2带进度条文件上传

    1.struts2 带进度条文件上传 源码 2.源码中有lib 下载后部署马上就能用 3.代码中有详细的注释信息 4.对关键点有详细的解释说明 5.如果谁用起来觉得有问题可在评论留言,留联系方式,我会联系你的 6.非常感谢原创作者...

    struts2实现文件上传显示进度条效果

    总的来说,Struts2实现文件上传显示进度条效果需要理解文件上传的处理流程,创建一个监听器来捕获上传进度,并通过合适的通信机制将这些信息传递到前端进行显示。这是一个涉及到后端处理、前端交互以及网络通信的...

    struts1.2下实现文件上传进度条

    ### Struts 1.2 下实现文件上传进度条的关键知识点 #### 一、背景与目的 在基于Struts 1.2的Web应用中,实现文件上传时常常需要提供一个友好的用户界面来显示文件上传进度。这不仅提高了用户体验,还能够实时反馈...

    struts2(ssh)带进度条文件上传 demo 的jar包1

    在Struts2中,实现文件上传功能是非常常见的需求,而带进度条的文件上传则可以提供更好的用户体验,让用户了解文件上传的进度,减少用户的等待焦虑感。 Struts2的文件上传主要依赖于Apache的Commons FileUpload库。...

    struts 单文件上传和多文件上传带进度条

    在Struts中,可以实现单文件和多文件的上传,并且为了提升用户体验,我们还可以添加进度条来显示文件上传的状态。本文将详细介绍如何在Struts中实现这两个功能,并带上传进度条。 首先,我们需要了解Struts中处理...

    struts2多文件上传显示进度

    Struts2是一个非常流行的Java Web框架,...总的来说,Struts2多文件上传并显示进度的实现需要结合前端和后端的技术,通过AJAX和XMLHttpRequest的`onprogress`事件来动态更新进度条,同时确保后端处理的高效和安全性。

    ssh2(struts2+spring2.5+hibernate3.3+ajax)带进度条文件上传(封装成标签

    在这个项目中,Struts2提供了一套灵活的动作和拦截器机制,使得文件上传可以通过自定义Action类来实现,同时它支持与Ajax的交互,可以实现无刷新的进度条展示。 2. **Spring**:Spring框架是一个全面的企业级应用...

    struts2结合uploadify上传进度条

    在Struts2中集成Uploadify3.2.1可以让用户实现文件上传功能,并且带有进度条显示,增强了用户体验。Uploadify是一个JavaScript库,它利用Flash技术实现异步文件上传,并提供了自定义的进度条显示。 要实现"struts2...

    struts2 上传 带有进度条

    在Struts2中处理文件上传是一项常见的任务,尤其是当用户需要上传大文件时,提供一个带有进度条的界面可以显著提高用户体验。下面我们将深入探讨如何在Struts2中实现带进度条的文件上传。 1. **Struts2文件上传基础...

    利用struts2实现上传文件进度条

    // 更新进度条显示 }, complete: function() { setTimeout(uploadProgress, 1000); // 每秒查询一次 } }); } $(document).ready(uploadProgress); ``` 5. **创建界面** 创建一个简单的HTML页面,包含一个...

Global site tag (gtag.js) - Google Analytics