DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=20744>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=20744

HTTPClient MultiPartPostMethod inconsistent behaviour compared to standard form upload

           Summary: HTTPClient MultiPartPostMethod inconsistent behaviour
                    compared to standard form upload
           Product: Commons
           Version: unspecified
          Platform: Other
        OS/Version: Windows NT/2K
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: HttpClient
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


First of all, I am not sure whether I need to report the problem here or on the
Tomcat forum. However it is a bug which occupied two developpers for about two
days, so a solution might interest everyone. 

The used versions are : Commons HTTPClient 2beta1 and Tomcat 4.0.x. I did not
test whether the same behaviour occured using later versions of tomcat. All were
running on a WIN32 platform.

Situation:
I have a tomcat server running with struts. I created an action (call it
"FileUploadReceiveAction" which saves the uploaded file depending on another
submitted parameter "identification" either in directory A or directory B). Of
course, I created a corresponding actionform FileUploadReceiveForm.

When I use a simple HTML form with two fields : input-text-name=identification
and input-file-name=thefile, the file selected in "theFile" field and the
identification value are correctly uploaded and treated by my
FileUploadReceiveAction. The html form indicates "multipart/form-data".

Next step is to do the same thing but with httpclient.

The code is as follows : 

snip...
String connectURL = "http://localhost:8080/appl/upload.do";; //this the mapping
towards my FileUploadReceiveAction
HttpClient client = new HttpClient();
MultipartPostMethod method = new MultipartPostMethod(connectURL);
method.addParameter("identification", "default");
method.addParameter("theFile", "test.txt", new File("c:/temp/test.txt"));
int statuscode = client.executeMethod(method);
method.releaseConnection();

...end snip
(in case there is an error in the code above : my code at home compiles ok, so
it is probably a typing error).


Now here comes the particular "bugs":

1) bug one
on the server side, (i.e. in FileUploadReceiveAction) : 
request.getParameter("identification") gives the value
"Content-Transer-Encoding: 8bitdefault" as result
((FileUploadReceiveForm)form).getIdentification() gives
"Content-Transer-Encoding: 8bitdefault" as result

2) bug two
The file uploaded has an unexpected "\r\n" on the beginning of the file, which
quite disturbing when the uploaded file is an xml file which as a result of that
does not validate anymore.


I did some tracing on the POST body when submitted via the HTML form and via the
HTTPCLient : Remark the differences in the Part heading !

1) POST body submit via the HTTPClient: (Boundary =
------------------314159265358979323846)

------------------314159265358979323846
Content-Disposition: form-data; name="identification"
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

default
------------------314159265358979323846
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

SQuirreL SQL Client Session Dump Thu Mar 27 10:32:41 CET 2003 ...rest of file
follows
------------------314159265358979323846--

2) POST body submit via HTML Form: (Boundary =
-----------------------------41184676334)

-----------------------------41184676334
Content-Disposition: form-data; name="identification"

default
-----------------------------41184676334
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

SQuirreL SQL Client Session Dump Thu Mar 27 10:32:41 CET 2003 ...rest of file
follows
-----------------------------41184676334--


Conclusion : There is clearly a difference in the way the HTTPClient and the
HTML form send the same pieces of data. The differences are situated in the
MultiPart headers. The error is not due to struts ase both the get method on the
form as the getparameter on the request give the same result. The bug is
probably situated in Tomcat or the Multipart upload mechanism which parses the
headers incorrectly. 

I checked the RFCs and both Content-Transfer-Encoding (for both FilePart and
StringPart) and Content-type (for StringPart) are optional, non-mandatory.

Solution - Workaround : 
Create classes which enable you to simulate the Multipart headers as they are
sent by your browser. Overwriting the correct methods enables you to avoid that
the content-transfer-encoding and content-type headers are added to the
different parts.
Create the following classes : 
package whathever;
public class StringPart extends
org.apache.commons.httpclient.methods.multipart.StringPart {

        public StringPart(String name, String value) {
                super(name, value);
        }

protected void sendTransferEncodingHeader(OutputStream arg0)
                throws IOException {
        }

protected void sendContentTypeHeader(OutputStream arg0)
                throws IOException {
        }

}


package whatever;
public class FilePart extends
org.apache.commons.httpclient.methods.multipart.FilePart {
        public FilePart(String name, String filename, File file) throws
FileNotFoundException {
                super(name, filename, file);
        }
        protected void sendTransferEncodingHeader(OutputStream arg0)
                throws IOException {
        }
}

and adapt your HTTPCLient code to : 

snip...
String connectURL = "http://localhost:8080/appl/upload.do";; //this the mapping
towards my FileUploadReceiveAction
HttpClient client = new HttpClient();
MultipartPostMethod method = new MultipartPostMethod(connectURL);
Part part = new whatever.StringPart("identification", "default");
method.addPart(part);
FilePart filepart = new whatever.FilePart("theFile", "test.txt", new
File("c:/temp/test.txt"));
method.addPart(filePart);
int statuscode = client.executeMethod(method);
method.releaseConnection();


...end snip


And the bugs suddenly will disappear.

However I think this behaviour is a work around and not a definitive solution,
as the server which treats the POST does not read the Multipart headers correctly.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to