commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Egan, Russell" <Russell.E...@safenet-inc.com>
Subject [FileUpload] Problem uploading very small file with streaming API when unlying stream is reading very small chunks of the upload...
Date Thu, 18 Oct 2007 21:36:20 GMT
We've found in our application that files less than 45 bytes fail to
upload when we are using SSL.

 

Scenario:

1.       JBoss 4.2.1 and commons-fileupload 1.2

2.       SSL enabled

3.       Using streaming API

4.       Uploading file smaller than 45 bytes.

 

There seems to be an issue in
org.apache.commons.fileupload.MultipartStream which only arises if calls
to the underlying stream's read method return the data stream in small
chunks, rather than in one big chunk.

 

When we turn on SSL, the underlying SSL socket stream behaves this way.
The first call to read() returns:

 

-----------------------------188332183511578

Content-Disposition: form-data; name="ice.component"

 

ifSub:iceform:icepnltabset:inputFileName

-----------------------------188332183511578

Content-Disposition: form-data; name="ice.view.active"

 

1

-----------------------------188332183511578

Content-Disposition: form-data; name="upload"; filename="test.txt"

Content-Type: text/plain

 

Then the next  read() returns:

 

a

 

Then the next read() returns:

 

                -----------------------------188332183511578--

 

So the entire multipart contents is there in the stream, but it takes
multiple calls to read() to get it all.  This is perfectly acceptable
stream behavior.

 

The trouble is,
org.apache.commons.fileupload.MultipartStream.ItemInputStream#read()
fails to return any bytes if the number of bytes it reads off the
underlying stream are less than the size of the delimiter.

 

Note this code in
org.apache.commons.fileupload.MultipartStream.ItemInputStream#read()

 

          if (available() == 0) {

                if (makeAvailable() == 0) {

                    return -1;

                }

            }

 

See how if first checks whether any bytes are available, and if not, it
calls makeAvailable() to read more bytes into its buffer.  If
makeAvailable() returns 0, then read() returns -1, indicating the end of
the stream.  But makeAvailable() can return 0 even when the end of the
underlying stream hasn't been reached yet.

 

In makeAvailable(), you'll see it reads the next chunk of bytes off the
underlying stream, then returns the result of available().  But
available() looks like this:

 

      public int available() throws IOException {

            if (pos == -1) {

                return tail - head - pad;

            }

            return pos - head;

        }

 

When bytes have just been read from the underlying stream into buf, pos
is -1.  So tail - head - pad is returned.  Pad is set by
org.apache.commons.fileupload.MultipartStream.ItemInputStream#findSepara
tor() to be the number of bytes read when the number of bytes read is
less than the keepRegion (which is the size of the delimiter).  So if I
read 1 byte off the underlying stream (the "a" in the example above),
and the delimiter is 44 bytes (the
"-----------------------------188332183511578" in the example above),
then tail - head is 1, keepReqion is 44, so pad is set to -1, and hence
available() return tail - head - pad, which equals 0.  So even though
there is a byte in the buffer, and the underlying stream still isn't at
the end yet,
org.apache.commons.fileupload.MultipartStream.ItemInputStream#read() is
going to return -1, indicating end-of-stream.

 

Is this a bug?  It seems to be clearly incorrect behavior.  Thanks.


The information contained in this electronic mail transmission may be privileged and confidential,
and therefore, protected from disclosure. If you have received this communication in error,
please notify us immediately by replying to this message and deleting it from your computer
without copying or disclosing it.
Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message