users@jersey.java.net

Re: [Jersey] Multipart Post

From: Alexander Birmingham <alexx1523_at_gmail.com>
Date: Tue, 5 Jan 2010 11:40:20 -0800

Paul -

Through a lot of brute force debugging, I've narrowed down the problem to a
single line in the request.

*This works:*
Content-Type: multipart/form-data;
boundary=----------------------------4e1144df2bb2

*While this does not:*
Content-Type:
multipart/form-data;boundary=----------------------------4e1144df2bb2

Don't even want to admit how long it took for us to figure that one out.
Apparently the server gets confused if there is whitespace after the
semi-colon. This should probably become a bug report, but in the meantime
can I specify that line manually with the Jersey client?

Best Regards,
Alexander

On Tue, Jan 5, 2010 at 9:30 AM, Alexander Birmingham <alexx1523_at_gmail.com>wrote:

> Paul -
>
> Thanks for the quick response! I'm referencing the following libraries:
> *jersey-client-1.1.4.1.jar
> jersey-core-1.1.4.1.jar
> jsr311-api-1.1.jar
> activation-1.1.jar
> jersey-multipart-1.1.4.1.jar
> mail-1.4.jar
> mimepull-1.3.jar*
>
> Additionally, it may help to know that the Jersey client prints the
> following blurb when created:
> *Jan 5, 2010 9:16:32 AM com.sun.jersey.api.client.Client <init>
> INFO: Adding the following classes declared in
> META-INF/services/jersey-client-components to the client configuration:
> class com.sun.jersey.multipart.impl.MultiPartConfigProvider
> class com.sun.jersey.multipart.impl.MultiPartReader
> class com.sun.jersey.multipart.impl.MultiPartWriter*
>
> The server side processor is an internal tool to my company written in
> perl. Frankly I don't know a lot about it, but it is verified as functional
> according to the curl request. Additionally, Jersey has worked fine so far
> for my plain-jane getting/posting needs, so long as the request is composed
> entirely of ordinary query parameters. I should mention also that my client
> setup is fairly minimalistic: CLIENT = Client.create();. That's it :)
>
> Finally, I have revised the following line of code to use FormDataMultiPart
> as per your recommendation:
> *MultiPart multiPart = new FormDataMultiPart().bodyPart(new
> FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));*
>
> Other than above... I'm not sure what to think. Your code looks identical
> to mine, as far as I can tell, except that your request doesn't include
> query parameters in addition to the MultiPart. Could that be where I'm
> stumbling?
>
> Best Regards,
> Alexander
>
> On Tue, Jan 5, 2010 at 1:44 AM, Paul Sandoz <Paul.Sandoz_at_sun.com> wrote:
>
>> Hi Alexander,
>>
>> You client code looks fine. Although strictly speaking you should use an
>> instance of FormDataMultiPart.
>>
>> What version of Jersey are you using?
>>
>> What is the server side that consumes the request?
>>
>> Attached is a very simple client and server using Jersey which works fine.
>> And the server-side also works fine when i use curl to do send an equivalent
>> request.
>>
>> If you run this example (suitably modifying the file to send) you will
>> notice that Jersey will log the request received from the client:
>>
>> Jan 5, 2010 10:29:44 AM com.sun.jersey.api.container.filter.LoggingFilter
>> filter
>> INFO: 3 * Server in-bound request
>> 3 > POST http://localhost:8080/mavenproject9/webresources/myresource
>> 3 > content-type:
>> multipart/form-data;boundary=Boundary_1_2384204_1262683784353
>> 3 > mime-version: 1.0
>> 3 > user-agent: Java/1.5.0_20
>> 3 > host: localhost:8080
>> 3 > accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
>> 3 > connection: keep-alive
>> 3 > content-length: 1210
>> 3 >
>>
>> --Boundary_1_2384204_1262683784353
>> Content-Type: application/octet-stream
>> Content-Disposition: form-data;filename="a.patch";modification-date="Mon,
>> 07 Dec 2009 09:48:27 GMT";size=968;name="file"
>>
>> # This patch file was generated by NetBeans IDE
>> # Following Index: paths are relative to:
>> /Users/paulsandoz/Projects/atmosphere/trunk/atmosphere/modules/jersey/src/main/java/org/atmosphere/jersey
>> # This patch can be applied using context Tools: Patch action on
>> respective folder.
>> # It uses platform neutral UTF-8 encoding and \n newlines.
>> # Above lines and this line are ignored by the patching process.
>> Index: AtmosphereFilter.java
>> --- AtmosphereFilter.java Base (BASE)
>> +++ AtmosphereFilter.java Locally Modified (Based On LOCAL)
>> @@ -156,6 +156,9 @@
>> * @return the {_at_link ContainerResponse}
>> */
>> public ContainerResponse filter(ContainerRequest request,
>> ContainerResponse response) {
>> + if (response.getMappedThrowable() != null)
>> + return response;
>> +
>> AtmosphereResource r = (AtmosphereResource) servletReq
>>
>> .getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>>
>>
>> --Boundary_1_2384204_1262683784353--
>>
>>
>> Jan 5, 2010 10:29:44 AM
>> com.sun.jersey.api.container.filter.LoggingFilter$Adapter finish
>> INFO: 3 * Server out-bound response
>> 3 < 204
>> 3 <
>>
>>
>> Notice the Content-Disposition header:
>>
>> Content-Disposition:
>> form-data;filename="a.patch";modification-date="Mon, 07 Dec 2009 09:48:27
>> GMT";size=968;name="file"
>>
>> That contains the property "name" of the value "file".
>>
>> Note that you can also log from the client side as well by doing:
>>
>> Client c = ...
>> c.addFilter(new LoggingFilter());
>>
>> to also verify the Content-Disposition header.
>>
>> Paul.
>>
>>
>>
>> On Jan 5, 2010, at 1:31 AM, Alexander Birmingham wrote:
>>
>> Hi Everyone:
>>
>> I've been trying to do a multipart post using the Jersey Client, and it's
>> just about near driving me crazy. The examples I've found have been helpful
>> in modelling my code, but haven't taken me quite to the end.
>>
>> *I am looking to duplicate the following curl command:*
>>
>> curl -F "file=_at_test.zip;type=application/octet-stream" -F "e=
>> alexx1523_at_gmail.com" -F "l=iQdad" -F "t=5Cp" -F "client_id=1000076"
>> http://my.url.here.com/home/upload
>>
>> *This is my java code:*
>>
>> MultivaluedMap<String, String> queryParams;
>> File file = new File("/tmp/test.zip");
>>
>> addArgument(SessionUser.getCURRENTUSER()); // This adds the
>> parameters you see above to queryParams
>>
>> MultiPart multiPart = new MultiPart().bodyPart(new
>> FileDataBodyPart("file", file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
>>
>>
>> webResource.queryParams(queryParams).type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class,
>> multiPart);
>>
>> The response indicates that the post is missing field "file". I am unable
>> to determine if this is because the binary is not being attached correctly,
>> or if the attachment is not being sent with the correct name. The name has
>> to be "file", as occurs in the above curl, or it will not be recognized.
>>
>> Please help!
>>
>> Best Regards,
>> Alexander Birmingham
>>
>>
>>
>>
>