`
入云涛
  • 浏览: 155772 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

struts.multipart 和 commons-fileupload上传插件解析

    博客分类:
  • j2ee
阅读更多
使用的是struts2和commons-fileupload2.1.1
昨天遇到一个上传功能的错误,很是奇怪,原因是有的时候能够上传成功,有的不能上传成功,最为奇特的是需要报个错误,才能上传成功,不报错的就不能上传成功。今天算是弄清楚了,特地做个记录,首先报错的代码如下。
org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (5727) exceeds the configured maximum (4028)

但是奇怪的是,报错了我竟然能够把正确上传附件,反而是不报错的反而上传不了附件。上传附件代码如下
request.setCharacterEncoding("UTF-8");

		LoadPath loadPath = new LoadPath();
		String path = loadPath.getUploadPath();
		String fileName = "";

		boolean isFlg = false;

		Util u = new Util();
		// 判断有没有这个日期目录
		String currData = u.getSysDate("yyyyMMdd");
		// 判断目录在不,如果不在那么就添加一个目录
		path = path + "/" + currData;
		File dir = new File(path);
		if (!dir.exists()) {
			// 不存在,需要创建目录
			try {
				dir.mkdir();
				this.log("创建目录:" + dir);
			} catch (Exception ex) {
				log.error("创建目录:" + path + "失败,原因:" + ex.toString());
			}
		}
		// 文件上传部分
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		if (isMultipart == true) {
			DiskFileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
			try {
				List<FileItem> items = upload.parseRequest(request);// 上传文件解析
				Iterator<FileItem> itr = items.iterator();// 枚举方法
				while (itr.hasNext()) {
					FileItem item = (FileItem) itr.next();
					if (item.isFormField()) {// 判断是文件还是文本信息
					} else {
						if (item.getName() != null
								&& !item.getName().equals("")) {// 判断是否选择了文件

							long time = System.currentTimeMillis();
							String temPath = item.getName();// 返回上传文件在客户端的完整路径名称
							fileName = temPath.substring(temPath
									.lastIndexOf("\\") + 1, temPath.length());// 原来文件名
							String oldName = fileName.substring(0, fileName
									.lastIndexOf("."));// 文件名
							String fileNameAtt = fileName.substring(fileName
									.lastIndexOf(".") + 1, fileName.length());// 文件后缀名
							String newName = time + "." + fileNameAtt;

							// 此时文件暂存在服务器的内存当中
							log.info("保存地址:" + path);
							File file = new File(path, newName);
							// 获取根目录对应的真实物理路径
							item.write(file);// 保存文件在服务器的物理磁盘中
							// 上传文件成功!
							isFlg = true;
							String loadPathStr = "upload/"+currData+"/"+newName;
							AppContext.getWySysFileManagerLogic().save(oldName, time+"", loadPathStr, Integer.parseInt(item.getSize()+""));
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
				log.info("文件上传失败!");
			}
		} else {
			log.info("上传数据格式不是 multipart/form-data");
		}

根据调试发现,
List<FileItem> items = upload.parseRequest(request);// 上传文件解析
Iterator<FileItem> itr = items.iterator();// 枚举方法

这段代码在报错时,itr是有值的,而不报错的时候是没有值的。我很纳闷这究竟是怎么回事,在网上搜索了半天发现原来是我在struts.properties文件中把struts.multipart值设置的太小。我设置的值为
struts.multipart.maxSize=4028

原来是我上次的文件大于这个值是就报错,小于这个值时就不报错。将这个值修改为1000000后,发现这回文件就压根上次不了。只好设置值为10,继续报错,可是就可以上传了。找了好多资料也没有发现有价值的。只好找到struts2的源码和commons-fileupload-1.2.1源码。调试后终于发现我的错误是在org.apache.commons.fileupload.FileUploadBase类中
if (sizeMax >= 0) {
  int requestSize = ctx.getContentLength();
	if (requestSize == -1) {
	    input = new LimitedInputStream(input, sizeMax) {
		protected void raiseError(long pSizeMax, long pCount)
			throws IOException {
		    FileUploadException ex =
			new SizeLimitExceededException(
			    "the request was rejected because"
			    + " its size (" + pCount
			    + ") exceeds the configured maximum"
			    + " (" + pSizeMax + ")",
			    pCount, pSizeMax);
		    throw new FileUploadIOException(ex);
		}
	    };
	} else {
	    if (sizeMax >= 0 && requestSize > sizeMax) {
		throw new SizeLimitExceededException(
			"the request was rejected because its size ("
			+ requestSize
			+ ") exceeds the configured maximum ("
			+ sizeMax + ")",
			requestSize, sizeMax);
	    }
	}
    }

在这段代码里面,如果设置的sizeMax小于requestSize时就会报错。这回报错原因找到了,继续调试,发现在上传没有报错的附件调试中,有一个类JakartaMultiPartRequest中的parse方法,如下:
public void parse(HttpServletRequest servletRequest, String saveDir)
            throws IOException {
        DiskFileItemFactory fac = new DiskFileItemFactory();
        // Make sure that the data is written to file
        fac.setSizeThreshold(0);
        if (saveDir != null) {
            fac.setRepository(new File(saveDir));
        }

        // Parse the request
        try {
            ServletFileUpload upload = new ServletFileUpload(fac);
            upload.setSizeMax(maxSize);

            List items = upload.parseRequest(createRequestContext(servletRequest));

            for (Object item1 : items) {
                FileItem item = (FileItem) item1;
                if (LOG.isDebugEnabled()) LOG.debug("Found item " + item.getFieldName());
                if (item.isFormField()) {
                    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)
                    String charset = servletRequest.getCharacterEncoding();
                    if (charset != null) {
                        values.add(item.getString(charset));
                    } else {
                        values.add(item.getString());
                    }
                    params.put(item.getFieldName(), values);
                } else {
                    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());
                        continue;
                    }

                    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);
                }
            }
        } catch (FileUploadException e) {
            LOG.error("Unable to parse request", e);
            errors.add(e.getMessage());
        }
    }

里面files就是我要上传的附加信息,好终于找到了位置了。继续在附件很大时,上传要报错,就不会执行这个语句,此时在执行到List<FileItem> items = upload.parseRequest(request);就会获取到数据,这回终于弄清楚是怎么回事了。原来struts在请求时有一个参数struts.multipart.saveDir,其中值的就是在上传附件时,struts2已经和fileupload使用了默认的JakartaMultiPartRequest类上传了附件,那么我们再次使用fileupload组建获取附件时已经没有了,而报错时JakartaMultiPartRequest没有执行,所以可以使用fileupload获取附件,按这么说就只需要对上传附件做下修改就可以满足要求,再次debug发现,servlet的request对象原来是MultiPartRequestWrapper,在细看这个对象里面有一个值multi,multi有一个值为files。这会找到解决方法了,就是这个files把上传参数获取后,导致fileupload没有获取到。现在做如下修改:


今天太晚了,已经凌晨1点多了,明天继续补上
分享到:
评论
1 楼 lpwdhx123 2012-03-05  
收获颇多,谢谢你的文章,解决了我的燃眉之急

相关推荐

    commons-fileupload-1.3.3.jar和commons-io-2.6.jar

    在Java开发中,上传文件是一项常见的任务,而`commons-fileupload-1.3.3.jar`和`commons-io-2.6.jar`是Apache Commons项目中的两个重要库,专门用于处理HTTP请求中的文件上传功能。这两个库为开发者提供了便捷、高效...

    struts2上传文件需要的jar包 commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar

    在Struts2中处理文件上传功能时,通常需要依赖两个关键的第三方库:`commons-fileupload`和`commons-io`。这两个jar包在Java文件上传处理中扮演着至关重要的角色。 `commons-fileupload-1.2.1.jar`是Apache Commons...

    struts,springMVC 上传文件需要的jar包 commons-fileupload-1.2.1.jar和commons-io-1.3.2.jar

    总的来说,`commons-fileupload-1.2.1.jar`和`commons-io-1.3.2.jar`这两个库在Struts和Spring MVC中扮演着关键角色,使得处理文件上传变得更加便捷和可靠。开发者可以通过这些库提供的API轻松实现文件上传功能,...

    commons-fileupload-1.3.2.jar

    - Struts 2: 对于基于Struts 2的应用,可以通过配置`struts.multipart.parser`属性为`jakarta`来启用Apache Commons FileUpload。 总之,Apache Commons FileUpload是Java Web开发中处理文件上传不可或缺的工具,...

    commons-io-2.5.jar和commons-fileupload-1.4.jar

    标题中的"commons-io-2.5.jar"和"commons-fileupload-1.4.jar"是两个在Java开发中常用的库,分别属于Apache Commons IO和Apache Commons FileUpload项目。这两个库在处理输入/输出流和文件上传方面提供了强大的功能...

    commons-fileupload及源码

    7. **与其他库的集成**:Apache Commons FileUpload可与Servlet API、Spring MVC、Struts等Web框架无缝集成,简化了在这些框架中实现文件上传的复杂性。 源码分析对于理解其内部工作原理非常有帮助。`commons-...

    struts1.2和commons-fileupload实现文件上传

    Struts1.2和Commons-Fileupload是Java Web开发中用于实现文件上传的两个重要组件。Struts1.2是Apache的一个开源框架,主要用于构建MVC(模型-视图-控制器)架构的Web应用程序,而Commons-Fileupload则是Apache ...

    commons-fileupload-1.2.2-bin.zip

    总的来说,Apache Commons FileUpload库是Java开发人员处理文件上传问题的强大工具,它提供了一套完整的解决方案,包括解析请求、存储文件、错误处理和安全控制等。通过正确使用这个库,开发者可以避免手动处理复杂...

    struts2 文件下载需要的架包 commons-fileupload-1.2 commons-io-1.3.2

    这可能涉及到配置`&lt;constant&gt;`元素,将`struts.multipart.parser`设置为`jakarta`,因为Commons FileUpload与Servlet容器的内置解析器可能存在兼容性问题。 3. 创建一个Action类,定义一个`java.io.File`类型的属性...

    commons-fileupload-1.4.jar 和 commons-io-2.7.jar

    标题中的"commons-fileupload-1.4.jar"和"commons-io-2.7.jar"是两个在Java开发中常用的开源库,它们分别专注于文件上传处理和基础I/O操作。这两个库在Web应用开发,尤其是处理用户通过表单上传文件的情景下,扮演着...

    commons-fileupload-1.2.2.jar

    标题中的"commons-fileupload-1.2.2.jar"是一个Java库,它是Apache Commons FileUpload项目的版本1.2.2的实现。这个组件是专门设计用于处理HTTP协议中的文件上传功能,常见于Web应用程序,尤其是那些需要用户上传...

    commons-fileupload-1.2.1帮助文档

    《Java Web文件上传:commons-fileupload-1.2.1详解》 在Java Web开发中,文件上传是一项常见的功能,用户可能需要上传图片、文档等各类文件。Apache Commons FileUpload库是一个强大的工具,用于处理HTTP协议中的...

    commons-fileupload.jar

    "commons-fileupload.jar"负责处理文件上传,而"commons-collections.jar"和"commons-beanutils.jar"则提供了数据操作和处理的便利工具。这些库的组合使用能够帮助开发者更加高效地处理HTTP文件上传请求,并进行后续...

    commons-fileupload-1.2.1.jar commons-io-1.4.jar

    Struts2本身没有自带的两个jar 如果不导入的话会有Unable to load bean org.apache.struts2.dispatcher.multipart.MultiPartRequest (jakarta) - [unknown location]异常

    commons-fileupload-1.2.1.jar

    这个库是Apache Commons项目的一部分,由Apache软件基金会开发和维护,旨在简化在Java应用程序中处理用户通过表单提交的文件上传任务。 在Java Web开发中,标准的HTTP请求通常限制了POST数据的大小,这使得直接处理...

    使用commons-fileupload实现的文件上传和下载

    在Java Web开发中,文件上传和下载是常见的功能需求,Apache Commons FileUpload库提供了一种高效、方便的方式来处理这些操作。本教程将详细介绍如何利用commons-fileupload库来实现在Java Web应用中的文件上传和...

    commons-fileupload-1.2.1-bin 和 commons-io-1.4-bin.zip

    标题中的"commons-fileupload-1.2.1-bin"和"commons-io-1.4-bin.zip"分别指的是Apache Commons FileUpload 1.2.1版本和Apache Commons IO 1.4版本的二进制包。这两个组件在Java开发中扮演着重要的角色,尤其在处理...

    struts-2.5.2-all所有jar包

    commons-fileupload-1.3.2.jar, commons-io-2.4.jar, commons-lang-2.4.jar, commons-lang3-3.4.jar, commons-logging-1.1.3.jar, dwr-1.1.1.jar, ezmorph-1.0.6.jar, freemarker-2.3.23.jar, google-collections-...

    commons-fileupload-1.2.1.zip

    Commons FileUpload库是Apache Commons项目的一部分,旨在简化Web应用中处理multipart/form-data(即包含文件上传的表单)的过程。在传统的Servlet API中,文件上传处理相对复杂,而Commons FileUpload通过提供一套...

    struts-2.3.30-all所有jar包

    commons-fileupload-1.3.2.jar, commons-io-2.2.jar, commons-lang-2.4.jar, commons-lang3-3.2.jar, commons-logging-1.1.3.jar, commons-validator-1.3.1.jar, core-0.6.2.jar, dwr-1.1.1.jar, ezmorph-1.0.6.jar,...

Global site tag (gtag.js) - Google Analytics