Multipart with JSON in spring rest is not working - java

I am trying to create a method which accepts both multipart/form-data and application/json content type in same request. I am using Spring Rest for creating the same. But the call does not reach the method when I requested from Fiddler. Please help
Service method
#RequestMapping(value = "/", method = RequestMethod.POST, produces = "application/json",consumes = "multipart/form-data")
public ResponseEntity<JSONObject> addField( #RequestParam int customerId,#RequestParam int teId,
#RequestPart("file") List<MultipartFile> multipartFiles, #RequestParam("toast") String toast, MultipartHttpServletRequest request){
Fiddler
Header
Content-Type: multipart/form-data; boundary=HereGoes;
Body
Content-Type: application/json
---------------------------acebdf13572468
Content-Disposition: form-data; name="fieldNameHere"; filename="file1.pdf"
Content-Type: application/pdf
<#INCLUDE *C:\Users\User\Desktop\file1.pdf*#>
---------------------------acebdf13572468--

Add correct file name in request body of fiddler. In your method it is #RequestPart("file"). So use "file" in "name" field instead of "fieldNameHere" which is generated by fiddler. Your request body should look like below.
---------------------------acebdf13572468
Content-Disposition: form-data; name="file"; filename="file1.pdf"
Content-Type: application/pdf
<#INCLUDE *C:\Users\User\Desktop\file1.pdf*#>
---------------------------acebdf13572468--

Related

Jax RS: multipart/form-data boundary=----WebKitFormBoundary gives 415 unsupported media type

I have kendo upload widget send an uploaded file as Post request to the server; where JAX-RS is meant to handle it.
Looking at the network tab of chrome; here's what I see in the request:
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryARilQnC5oS7lnLVU
Request Payload
------WebKitFormBoundaryARilQnC5oS7lnLVU
Content-Disposition: form-data; name="files"; filename="test_blah.txt"
Content-Type: text/plain
------WebKitFormBoundaryARilQnC5oS7lnLVU--
on the server; here's how I've implemented the Post method
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void uploadFiles(#FormDataParam("files") List<InputStream> files) {
System.out.println("Reached UploadFiles");
}
I get an exception stating: Unsupported Media Type (415) on client side
and on server side:
javax.ws.rs.NotSupportedException: Could not find message body reader for type: class org.omg.CORBA.portable.InputStream of content type: multipart/form-data;boundary=----WebKitFormBoundaryARilQnC5oS7lnLVU
The kendo call looks like this:
<div class="demo-section k-content" ng-controller="UploadController">
<input name="files"
id="files"
type="file"
kendo-upload="uploader"
k-select="onSelect"
k-async="{ saveUrl: 'http://localhost:8080/path/to/upload', autoUpload: true }"/>
</div>
Can any one give me pointers on
How to accept the multipart/form-data request for this?
What's causing the Jax Rs to give this error? Is it the
WebKitFormBoundary bit? and How can I make the server side code
deal with this?

Java MultiPart post

I am trying to create a multipart post to a URL with the following body:
Content-Disposition: form-data; name="json"
Content-Type: "application/json; charset=UTF-8"
{"input1":"data1","input2":"data2","input3":"data3"}
--APIMultipartPost
Content-Disposition: form-data; name="filePath"; filename="myFile.dat"
Content-Length: 381645
Content-Type: text/plain
Content-Transfer-Encoding: binary
<!-- SNIP -->
<!-- The OWL file was included here in plain text (without the SNIPs) -->
<!-- SNIP -->
I tried using MultipartEntityBuilder to create the multipart post, but probably I do something wrong with the parameters.
Can someone help me with the java code for this post?
Here is my code:
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost(URL);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("input1", "data1");
builder.addTextBody("input2", "data2");
builder.addTextBody("input3", "data3");
builder.addBinaryBody("file", new File("C:/myFile.dat"), ContentType.APPLICATION_OCTET_STREAM, "myFile.dat");
HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
HttpResponse response = httpClient.execute(uploadFile);
and the error I get:
HttpResponseProxy{HTTP/1.1 422 Unprocessable Entity [Server: nginx/1.6.0, Date: Wed, 28 Jan 2015 19:29:42 GMT, Content-Type: application/json;charset=utf-8, Content-Length: 89, Connection: keep-alive, Status: 422 Unprocessable Entity, X-Rack-Cache: invalidate, pass, X-Content-Type-Options: nosniff] ResponseEntityProxy{[Content-Type: application/json;charset=utf-8,Content-Length: 89,Chunked: false]}}
Thank you!
The response 422 Unprocessable Entity says
The 422 (Unprocessable Entity) status code means the server
understands the content type of the request entity (hence a
415(Unsupported Media Type) status code is inappropriate), and the
syntax of the request entity is correct (thus a 400 (Bad Request)
status code is inappropriate) but was unable to process the contained
instructions. For example, this error condition may occur if an XML
request body contains well-formed (i.e., syntactically correct), but
semantically erroneous, XML instructions.
so as you can see the request you send doesn't fit with the specification of the controller/service that you POST to. If you use a tool like TCPMon you can actually intercept the request that you send and check how it looks like. When I do it with your code, it looks like
POST /url HTTP/1.1
Content-Length: 739
Content-Type: multipart/form-data; boundary=L2EqtNqIEXOWRCYYrYH8FSP1JAD65wz6c
Host: 127.0.0.1:8090
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.3.6 (java 1.5)
Accept-Encoding: gzip,deflate
--L2EqtNqIEXOWRCYYrYH8FSP1JAD65wz6c
Content-Disposition: form-data; name="input1"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
data1
--L2EqtNqIEXOWRCYYrYH8FSP1JAD65wz6c
Content-Disposition: form-data; name="input2"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
data2
--L2EqtNqIEXOWRCYYrYH8FSP1JAD65wz6c
Content-Disposition: form-data; name="input3"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
data3
--L2EqtNqIEXOWRCYYrYH8FSP1JAD65wz6c
Content-Disposition: form-data; name="file"; filename="myFile.dat"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
--L2EqtNqIEXOWRCYYrYH8FSP1JAD65wz6c--
which is not what you want. You only need a request with two parts, one is the json data and the other is the file.
So if you change your code as the following.
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("http://localhost:8090/1");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
String jsonStr = "{\"input1\":\"data1\",\"input2\":\"data2\",\"input3\":\"data3\"}";
builder.addTextBody("json", jsonStr, ContentType.APPLICATION_JSON);
builder.addBinaryBody("file", new File("/path/to/file"),
ContentType.TEXT_PLAIN, "myFile.dat");
HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
HttpResponse response = httpClient.execute(uploadFile);
You can provide a request like the following.
POST /url HTTP/1.1
Content-Length: 468
Content-Type: multipart/form-data; boundary=mN_bWsS4QQnlPJksvinB_WUpl2Qi6zVVElUEEBKh
Host: 127.0.0.1:8090
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.3.6 (java 1.5)
Accept-Encoding: gzip,deflate
--mN_bWsS4QQnlPJksvinB_WUpl2Qi6zVVElUEEBKh
Content-Disposition: form-data; name="json"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
{"input1":"data1","input2":"data2","input3":"data3"}
--mN_bWsS4QQnlPJksvinB_WUpl2Qi6zVVElUEEBKh
Content-Disposition: form-data; name="file"; filename="myFile.dat"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: binary
--mN_bWsS4QQnlPJksvinB_WUpl2Qi6zVVElUEEBKh--
which is what you need.
For multipart request, the content-type has to be multipart/form-data, then you specify content-type for each content. You might want to refer to w3.org - Introduction to forms for the HTTP header examples.

http file upload response structure

i am trying to create an http file upload receiver in java
and i was looking at the post response of file upload in http
POST /upload?upload_progress_id=12344 HTTP/1.1
Host: localhost:3000
Content-Length: 1325
Origin: http://localhost:3000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryePkpFF7tjBAqx29L
<other headers>
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="MAX_FILE_SIZE"
100000
------WebKitFormBoundaryePkpFF7tjBAqx29L
Content-Disposition: form-data; name="uploadedfile"; filename="hello.o"
Content-Type: application/x-object
<file data>
------WebKitFormBoundaryePkpFF7tjBAqx29L--
if the boundary string will be a part of the file that is being uploaded (by coincidence) how can i detect it ? is that even possible?
Well, as section 4.1 of RFC 2388 states:
4.1 Boundary
As with other multipart types, a boundary is selected that does not occur in any of the data.
So I guess that your browser will probably be smart enough to choose an appropriate boundary.

Java library for reading multipart/form-data http body containing multiple files

Basically, the following is what the format of data look like (it should follow HTTP standard format)
Content-Type: multipart/form-data; boundary=--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f
--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f
Content-Disposition: form-data; name="foo1.jpg"; filename="foo1.jpg"
Content-Length: 5578
Content-Type: image/jpeg
<image data 1 omitted>
--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f
Content-Disposition: form-data; name="foo2.jpg"; filename="foo2.jpg"
Content-Length: 327
Content-Type: image/jpeg
<image data 2 omitted>
--3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f--
You can take a look at this question which recommends using Apache Commons File upload

MimeMessage Content-Transfer-Encoding issue

Greetings all...
I am hoping somebody can shed me some lights about the issue I am having.
Reading the Javadoc of MimeMessage's getInputStream(), it says "Return a decoded input stream for this Message's content"
However, this is not what I am experiencing. The output is not decoded. For instance, if I have a message a follows
Date: Wed, 24 Feb 2010 11:29:13 +1100
From: xxxxxxxxx
To: xxxxxxxxxxxx
Message-ID: <4B8472D9.5050901#xxxxxxxxx>
Subject: xxxxxxxxxxxxxxxxxx
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------000801030004000206000901"
Content-Transfer-Encoding: quoted-printable
Organization: xxxxxxxxxxxxxxxxxx
User-Agent: Thunderbird 2.0.0.23 (Windows/20090812)
This is a multi-part message in MIME format.
--------------000801030004000206000901
Content-Type: text/plain; charset=3DISO-8859-1; format=3Dflowed
Content-Transfer-Encoding: 7bit
!
--------------000801030004000206000901
Content-Type: text/plain;
name=3D"bla.bla"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
filename=3D"bla.bla"
my.username =3D holly
my.host =3D molly
--------------000801030004000206000901--
Then, assuming that I have an object called 'm' constructed with the above content, then calling m.getInputStream() and dump the output to the screen shows those '=3D' charsets.
What did I do wrong?
If I used QPDecoderStream to decode the output of m.getInputStream() then of course the result will be correct. However, it defeat the purpose, because the Javadoc says getInputStream() returns a decoded input stream.
The issue here is that the message is malformed. You're not allowed to set Content-Transfer-Encoding to quoted-printable on a multipart part:
If a Content-Transfer-Encoding header field appears as part of a
message header, it applies to the entire body of that message. If a
Content-Transfer-Encoding header field appears as part of an entity's
headers, it applies only to the body of that entity. If an entity is
of type "multipart" the Content-Transfer-Encoding is not permitted to
have any value other than "7bit", "8bit" or "binary".
You could probably get the top-level MimeMessage's decoded content stream and instantiate a MimeMultipart from it, but that's just hacking around the fundamental problem of a broken message.

Categories