Apache Commons 文件上传 - 流意外结束

Apache Commons File Upload - Stream ended unexpectedly(Apache Commons 文件上传 - 流意外结束)

本文介绍了Apache Commons 文件上传 - 流意外结束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗯,我不得不说,到目前为止,这个让我很难过.我们在 Tomcat 6.0.18 中运行的 Web 应用程序在文件上传期间失败,但仅当客户端机器是 windows 机器时,仅适用于某些机器,适用于所有浏览器,而不仅仅是 IE.

Well, I have to say that so far, this one has me stumped. Our web application, which is running in Tomcat 6.0.18 is failing during file upload, but only when the client machine is a windows machine, only for some machines, and for all browsers, not just IE.

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

There is a stack trace in the logs, which seems to indicate that the client either closed the connection, or the stream was somehow corrupted. The root cause in the stack trace is given as follows:

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

导致跟踪的代码看起来相当简单.

The code which causes the trace looks fairly straight forward.

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;
}

让我们感到悲伤的是这一行:

The line which is giving us the grief is this one:

List<DiskFileItem> fileItems = upload.parseRequest(request);

出于某种原因,这决定了来自某些 Windows 机器的流在某种程度上已损坏.

Which for some reason is deciding that streams from some Windows machines are in some way corrupted.

我想我找到了一些可能相关的/a> 在 StackOverflow 上.似乎表明 Tomcat 6 中存在一些错误,该错误已在版本 6.0.20 中得到修复,比我们使用的版本略高.不幸的是,它没有提到问题本身是什么.我已经看过 Tomcat 变更日志,但不能看不到任何可能导致此问题的错误的候选对象.

I think I have found something that may be related on StackOverflow. It seems to suggest there is some bug in Tomcat 6 which was fixed in version 6.0.20, a slightly higher version than the one we're using. Unfortunately it doesn't mention what the issue itself was. I've had a look at the Tomcat changelog, but can't see any likely candidates for a bug which could cause this problem.

无论如何,关于我的实际问题,有没有人遇到过类似的问题,如果有,根本问题是什么以及您是如何解决的?

Anyway, on to my actual question, has anyone encountered a similar problem, and if so, what was the underlying issue and how did you resolve it?

提前感谢您的任何回复.

Thank you in advance for any responses.

这似乎是负载平衡和 Tomcat 的某种问题.如果您绕过负载均衡器并直接通过服务器 IP 地址访问 Tomcat,问题就会消失.奇怪的是,这出现在我们使用 Apache/AJP1.3 的暂存环境和我们使用 Zeus 的生活环境中.

This appears to be some kind of problem with load balancing and Tomcat. If you bypass the load balancer and access Tomcat directly via the server IP address, the problem goes away. The strange thing is that this appears in both our staging environment, in which we use Apache/AJP1.3, and live, where we use Zeus.

这原来是客户端防火墙的问题.当他们说他们肯定知道这不是防火墙问题时,他们似乎.. er.. 并不完全真实.

This turned out to be an issue with the clients firewall. It appears that they were.. er.. not being entirely truthful when they said that the knew definitely this was not a Firewall issue.

推荐答案

可能你需要tcpdump/wireshark的坏和右上传,然后比较一下?

May be you need tcpdump/wireshark bad and right uploads, and then compare them?

这篇关于Apache Commons 文件上传 - 流意外结束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:Apache Commons 文件上传 - 流意外结束

基础教程推荐