【发布时间】:2011-03-16 21:10:34
【问题描述】:
嗯,我不得不说,到目前为止,这个让我很难过。我们在 Tomcat 6.0.18 中运行的 Web 应用程序在文件上传期间失败,但仅当客户端机器是 Windows 机器时,仅适用于某些机器,适用于所有浏览器,而不仅仅是 IE。
日志中有一个堆栈跟踪,这似乎表明客户端关闭了连接,或者流以某种方式损坏。堆栈跟踪中的根本原因如下:
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 机器的流在某种程度上已损坏。
我想我在 StackOverflow 上找到了 that may be related 的东西。似乎表明 Tomcat 6 中存在一些错误,该错误已在版本 6.0.20 中修复,比我们使用的版本略高。不幸的是,它没有提到问题本身是什么。我在 Tomcat 更改日志中已had a look,但看不到任何可能导致此问题的错误的候选者。
无论如何,关于我的实际问题,有没有人遇到过类似的问题,如果有,根本问题是什么?您是如何解决的?
提前感谢您的任何回复。
编辑:这似乎是负载平衡和 Tomcat 的某种问题。如果您绕过负载均衡器并直接通过服务器 IP 地址访问 Tomcat,问题就会消失。奇怪的是,这出现在我们使用 Apache/AJP1.3 的暂存环境和使用 Zeus 的生活环境中。
EDIT3:这原来是客户端防火墙的问题。当他们说他们肯定知道这不是防火墙问题时,他们似乎.. er.. 并不完全真实。
【问题讨论】:
-
您是否愿意在回答此问题时详细说明问题所在?
-
马特,对不起,我不知道防火墙问题到底是什么。客户在防火墙修复后与我们联系并告知这是防火墙问题。
标签: java apache file-upload upload tomcat6