日期:2014-05-17  浏览次数:20664 次

Ext + org.apache.commons.fileupload上传文件
      在项目中一直使用struts的FormFile上传文件,后来发现这种方式存在一些缺陷:上传前后文件的大小不一致,主要取决于写入stream的时候byte数组大小的设置,
code="java"]
            byte[] temp = new byte[BUFFER_SIZE];
            BufferedInputStream bi = new BufferedInputStream(file.getInputStream(),BUFFER_SIZE);
            BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(tempPath));
            while (bi.read(temp) != -1) {
                bo.write(temp);
            }[

如果数组大小设置为1024字节,则每次写入1024字节,但是,如果在最后一次写入的时候原始文件中的字节数不到1024,这是仍然写入1024字节,这就导致在上传文件前后,文件大小不一致的问题,为了解决这个问题采用了apache的commons.fileupload上传文件,此方式在上传前后文件大小一致,至于是如何write的需要进一步研究。具体方式如下:

1. 前台ext需要设置formPanel的fileUpload属性为true,如果前台用jsp需要设置表单form的enctype="multipart/form-data"属性。

2. formPanel用submit方式提交。  

上传文件部分代码如下:
public static String upload (String dir, HttpServletRequest request)  {
        
		DiskFileUpload fu = new DiskFileUpload();
		//最多上传3G的数据   
		fu.setSizeMax(1024 * 1024 * 1024 * 3);   
		//超过1M的字段数据采用临时文件缓存   
		fu.setSizeThreshold(1024 * 1024);   
		//采用默认的临时文件存储位置   
		//fu.setRepositoryPath(...);   
		//设置上传的普通字段的名称和文件字段的文件名所采用的字符集编码   
		fu.setHeaderEncoding("utf-8");   

		//得到所有表单字段对象的集合   
		List fileItems = null;
		try {
			fileItems = fu.parseRequest(request);
		} catch (FileUploadException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}   
		
		//处理每个表单字段   
		Iterator i = fileItems.iterator();
		String targetName = null;//目标文件名
		while (i.hasNext()){  
			FileItem fi = (FileItem) i.next();   
			if (!fi.isFormField()){
				try {
					String pathSrc = fi.getName();//获取上传文件路径
					pathSrc = new String(pathSrc.getBytes("ISO-8859-1"),"UTF-8");
					if(pathSrc.trim().equals(""))   
					{   
						continue;   
					}   
					int start = pathSrc.lastIndexOf('\\');   
					String tempName = pathSrc.substring(start + 1);//获取上传文件名 
					String fileName = DateUtils.getNowLongTime();//新的文件名
					
					if(tempName.indexOf(".") < 0){//如果文件没有后缀
						targetName = fileName;
		            }else{
		            	int index = tempName.lastIndexOf(".");
		            	targetName = fileName+tempName.substring(index);//fileName+文件后缀
		            }
					
					File pathDest = new File(dir, targetName);   
					fi.write(pathDest);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					fi.delete();
				} 

			}   
		}
		
		return targetName.replace("\\", "/");
    }



需要注意事项:ext的Formpanel不需设置对应的ActionForm,否则fileItems = fu.parseRequest(request);无法获取表单输入项列表,表单中的参数用request.getParameter()来获取,
struts-config.xml

    <action path="/uploadaction"
            name="TestForm"         <!–指定formbean–><!--这里不用指定-->
     type="UploadAction"
     parameter="method" >
     <forward name="success" path="/success.jsp" />
</action>

现象:在struts-config.xml文件中,如果指定了formbean——name="TestForm" ,则文件无法正确上传,UploadAction中的fu.parseRequest( request)方法返回值为null;如果去掉了说明formbean的name属性,则文件可以正常上传。

原因:struts的RequestProccessor.process已经包含了处理文件上传的方法。如果在action配置中设置了formbean ,那么在你自己的action处理request之前,struts已经在RequestProccessor.populate方法中处理了request,因此,在自己的action中就取不到上传的文件了。

处理:如果要自己在action中处理文件上传工作,那么就不要在配置文件中配置formbean。


感谢