那么,我不得不说,到目前为止,这一个让我难住。 我们在Tomcat 6.0.18中运行的Web应用程序在file upload过程中失败,但是只有当客户端机器是Windows机器时,只有一些机器和所有浏览器,而不仅仅是IE 。
在日志中有一个堆栈跟踪,这似乎表明客户端closures了连接,或者stream被破坏了。 堆栈跟踪的根本原因如下:
Caused by: org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:983) at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:887) at java.io.InputStream.read(InputStream.java:85) at org.apache.commons.fileupload.util.Streams.copy(Streams.java:94) at org.apache.commons.fileupload.util.Streams.copy(Streams.java:64) at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:362) ... 70 more
导致跟踪的代码看起来相当简单。
private Map<String, Object> getMap( ActionRequest request ) { HashMap<String, Object> parameters = new HashMap<String, Object>(); if ( request == null ) { return parameters; } if ( request.getContentType() == null ) { return parameters; } try { if(PortletFileUpload.isMultipartContent(request)){ DiskFileItemFactory factory = new DiskFileItemFactory(); PortletFileUpload upload = new PortletFileUpload(factory); List<DiskFileItem> fileItems = upload.parseRequest(request); for( DiskFileItem fileItem : fileItems ) { String name = fileItem.getFieldName(); //now set appropriate variable, populate hashtable if( fileItem.isFormField() ) { String value = fileItem.getString( request.getCharacterEncoding() ); if( parameters.get( name ) == null ) { String[] values = new String[1]; values[0] = value; parameters.put( name, values ); } else { Object prevobj = parameters.get( name ); if( prevobj instanceof String[] ) { String[] prev = ( String[] ) prevobj; String[] newStr = new String[prev.length + 1]; System.arraycopy( prev, 0, newStr, 0, prev.length ); newStr[prev.length] = value; parameters.put( name, newStr ); } else { //now what? I think this breaks the standard. throw new EatMyHatException( "file and input field with same name?" ); } } } else { // Yes, we don't return FileParameter[] for multiple files of same name. AFAIK, that's not allowed. FileParameter fp = new FileParameter( fileItem ); parameters.put( name, fp ); files.add( fp ); } } } else { // Not multipart return toObjectMap(request.getParameterMap()); } } catch (FileUploadException e) { throw new RuntimeException(e); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } return parameters; }
让我们悲痛的是这一条:
List<DiskFileItem> fileItems = upload.parseRequest(request);
由于某种原因,它正在决定来自某些Windows机器的数据stream在某种程度上已经损坏。
我想我已经find了一些可能与 StackOverflow 相关的东西。 似乎表明在Tomcat 6中有一些错误,在6.0.20版本中修复了一个比我们使用的稍高的版本。 不幸的是,它没有提到问题本身。 我看了一下 Tomcat的更新日志,但看不到任何可能导致此问题的bug。
无论如何,在我的实际问题上,有没有人遇到类似的问题,如果是这样,那么根本问题是什么,你是如何解决的?
提前谢谢你的回复。
编辑:这似乎是负载平衡和Tomcat的某种问题。 如果绕过负载平衡器并直接通过服务器IP地址访问Tomcat,问题就会消失。 奇怪的是,这出现在我们使用Apache / AJP1.3的分段环境中,而在我们使用Zeus的地方。
编辑3:这原来是客户端防火墙的问题。 看来,他们是……呃,当他们说明确知道这不是一个防火墙问题时,他们并不是完全真实的。
可能是你需要tcpdump / wireshark坏和右上传,然后比较它们?