2010-07-16 80 views
5

那么,我不得不说,迄今为止,这一个让我难住。我们在Tomcat 6.0.18中运行的Web应用程序在文件上载过程中失败,但仅当客户端机器是Windows机器时,仅适用于某些机器和所有浏览器,而不仅仅是IE时,Apache Commons文件上传 - 流意外结束

日志中有一个堆栈跟踪,这似乎表明客户端关闭了连接,或者流以某种方式损坏了。堆栈跟踪的根本原因如下:

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中存在一些bug,它在6.0.20版本中修复了一个稍微高于我们正在使用的版本的版本。不幸的是,它没有提到问题本身。我在Tomcat changelog上有had a look,但是看不到任何可能导致此问题的bug。

无论如何,关于我的实际问题,有没有人遇到类似的问题,如果是的话,那么根本问题是什么,你是如何解决它的?

非常感谢您的回复。

编辑:这似乎是负载平衡和Tomcat的某种问题。如果绕过负载均衡器并直接通过服务器IP地址访问Tomcat,问题就会消失。奇怪的是,这出现在我们使用Apache/AJP1.3的分段环境中,以及我们使用Zeus的live中。

编辑3:这原来是客户端防火墙的问题。看起来他们是..呃..当他们说明确知道这不是防火墙问题时,他们并不完全真实。

+0

你愿意详细说明这个问题的答案究竟是什么吗? – MattC 2011-01-14 16:09:57

+0

Matt,我很抱歉,但我不确切知道防火墙问题是什么。我们只是简单地联系客户后的防火墙修复程序,并通知它是一个防火墙问题。 – Jon 2011-01-24 12:53:18

回答

1

可能是你需要tcpdump/wireshark坏和右上传,然后比较它们?

+0

是的,我们的确使用Wireshark来做这件事,说实话我没有什么经验解释。事实上,这个问题是间歇性的,很难再现,因此变得更加困难。无论如何,它竟然是防火墙。 – Jon 2011-01-24 12:55:40