Making an HttpRequest with MultipartEntity in it - java

I've been frustrated at trying to figure out how to make an http request with a multipart entity in it. The multipart has a custom boundary but I can't seem to be able to set it. My code below results in a response message of saying that my message does not contain multiple parts.
HttpPut addDoc = new HttpPut(url);
addDoc.addHeader("Content-Type", "multipart/related; boundary=\"END_OF_PART\"");
String bodyString = "Test for multipart update";
String titleString = "Title Test for multipart update";
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
StringBody title = new StringBody(titleString, "application/atom+xml",Charset.forName("UTF-8"));
StringBody body = new StringBody(bodyString, "text/plain",Charset.forName("UTF-8"));
entity.addPart("title", title);
entity.addPart("body", body);
addDoc.setEntity(entity);

you can try to remove addHeader part from your code and change your constructor to
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,null,Charset.forName("UTF-8"));

First of all you could try using:
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
which is the correct way to initialize it, and then:
addDoc.setEntity(entity.build());
as for the boundary your question is not clear whether you need to read a custom boundary or set it, anyway the custom boundary is set in the following way;
multipartEntity.setBoundary("some-mimetype-boundary-unique-string");

Related

File attachment with REST API

The below code is working fine to attach file in JIRA, only one problem is here
I can't use MultipartEntityBuilder as it needed to add new dependency in pom and that is not permissible , can any one please suggest which basic API I can use there? thanks in advance
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost postRequest = new HttpPost("https://xxxx.zzzz.net/rest/api/2/issue/" + issueID +"/attachments");
postRequest.setHeader("Authorization", "Basic <AUTHSTRING>");
postRequest.setHeader("X-Atlassian-Token", "nocheck");
File file = new File("C:\\Users\\MKumar\\Desktop\\Oauth_JIRA.rtf");
URL url = new URL("C:\\Users\\MKumar\\Desktop\\Oauth_JIRA.rtf");
MultipartEntityBuilder builder = MultipartBodyBuilder.create();
// This attaches the file to the POST:
builder.addBinaryBody(
"file",
new FileInputStream(file),
ContentType.MULTIPART_FORM_DATA,
file.getName()
);
HttpEntity multipart = builder.build();
postRequest.setEntity(multipart);
HttpResponse response = httpClient.execute(postRequest);
org.apache.http.entity.mime.MultipartEntity is deprecated as a result you'll have to use MultipartEntityBuilder.
For more related post please see this thread

How can I get a custom Content-Disposition line using Apache httpclient?

I am using the answer here to try to make a POST request with a data upload, but I have unusual requirements from the server-side. The server is a PHP script which requires a filename on the Content-Disposition line, because it is expecting a file upload.
Content-Disposition: form-data; name="file"; filename="-"
However, on the client side, I would like to post an in-memory buffer (in this case a String) instead of a file, but have the server process it as though it were a file upload.
However, using StringBody I cannot add the required filename field on the Content-Disposition line. Thus, I tried to use FormBodyPart, but that just put the filename on a separate line.
HttpPost httppost = new HttpPost(url);
MultipartEntity entity = new MultipartEntity();
ContentBody body = new StringBody(data,
org.apache.http.entity.ContentType.APPLICATION_OCTET_STREAM);
FormBodyPart fbp = new FormBodyPart("file", body);
fbp.addField("filename", "-");
entity.addPart(fbp);
httppost.setEntity(entity);
How can I get a filename into the Content-Disposition line, without first writing my String into a file and then reading it back out again?
Try this
StringBody stuff = new StringBody("stuff");
FormBodyPart customBodyPart = new FormBodyPart("file", stuff) {
#Override
protected void generateContentDisp(final ContentBody body) {
StringBuilder buffer = new StringBuilder();
buffer.append("form-data; name=\"");
buffer.append(getName());
buffer.append("\"");
buffer.append("; filename=\"-\"");
addField(MIME.CONTENT_DISPOSITION, buffer.toString());
}
};
MultipartEntity entity = new MultipartEntity();
entity.addPart(customBodyPart);
As a cleaner alternative to creating an extra anonymous inner class and adding side effects to protected methods, use FormBodyPartBuilder:
StringBody stuff = new StringBody("stuff");
StringBuilder buffer = new StringBuilder();
buffer.append("form-data; name=\"");
buffer.append(getName());
buffer.append("\"");
buffer.append("; filename=\"-\"");
String contentDisposition = buffer.toString();
FormBodyPartBuilder partBuilder = FormBodyPartBuilder.create("file", stuff);
partBuilder.setField(MIME.CONTENT_DISPOSITION, contentDisposition);
FormBodyPart fbp = partBuilder.build();

Android multipart upload + blueimp UploadHandler: filetype not allowed

I'm trying to get my Android multipart image upload to work with the default blueimp PHP UploadHandler, which I'm using for the web version of my app.
It didn't work out of the box, so I experimented with the header of the requests.
I played around with it for quite a while, but since nothing worked I ended up firing up Wireshark and comparing the packets of the blueimp demo and the ones that are sent by the Android app.After some further tweaking, they look exactly the same (well the important parts):
Blueimp demo: http://i.imgur.com/T9styyR.png
Android MultipartEntity: http://i.imgur.com/OuDuyJ0.png
This is what my customized generate_response function returns:
Array
(
[0] => stdClass Object
(
[name] => 1387215600-9207
[size] => 97894
[type] => multipart/form-data; boundary=-----Don'tmindmeI'mjustaboundary
[error] => Filetype not allowed
)
)
It seems to load the whole packet instead of just it's multipart part.
Is there any way to fix that?
Here's how I create the request (not quite but these are the relevant lines):
public static String BOUNDARY = "-----Don'tmindmeI'mjustaboundary";
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, BOUNDARY, null);
File file = new File(params[2]); //params[2] contains the absolute path + filename
String filename = file.getName();
entity.addPart(filename, new FileBody(file, getMimeType(params[2]))); //getMimeType returns the MIME Type of the image e.g. image/png
HttpPost request = new HttpPost(params[0]); //params[0] contains the URL
request.setHeader("Content-Type", "multipart/form-data; boundary="+BOUNDARY);
request.setEntity(entity);
HttpResponse response = client.execute(request, context);
I've been working on this for hours and it's really driving me nuts.
What am I doing wrong?
Edit:
Nevermind I got it to work
I forgot to set the name of the form to files[], which is what the UploadHandler is looking for ...
So now it looks like this:
...
public static String BOUNDARY = "-----Don'tmindmeI'mjustaboundary";
...
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, BOUNDARY, null);
File file = new File(params[2]);
String filename = file.getName();
FileBody body = new FileBody(file, getMimeType(params[2]));
FormBodyPart part = new FormBodyPart("files[]", body);
part.addField("Content-Type", getMimeType(params[2]));
part.addField("Content-Disposition", "form-data; filename=\""+filename+"\"");
entity.addPart(part);
HttpPost request = new HttpPost(params[0]);
request.setHeader("Content-Type", "multipart/form-data; boundary="+BOUNDARY);
request.addHeader("Accept", "application/json, text/javascript, */*; q=0.01");
request.addHeader("Accept-Language", "en-US,en;q=0.8,de;q=0.6,es;q=0.4");
request.setEntity(entity);
HttpResponse response = client.execute(request, context);
...

Content length? Length required but set?

I am trying to send data to a web server using a post, this is what I have so far:
private void entity(String id, String file)
throws JSONException, UnsupportedEncodingException, FileNotFoundException {
// Add your data
File myFile = new File(
Environment.getExternalStorageDirectory(), file);
InputStreamEntity reqEntity = new InputStreamEntity(
new FileInputStream(myFile), myFile.length());
reqEntity.setContentType("text/csv");
reqEntity.setChunked(true); // Send in multiple parts if needed
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("project", id));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httppost.setEntity(reqEntity);
//httppost.setHeader("Content-Length", String.valueOf(myFile.length()));
}
When I send the post request it comes back with content-length required, but isn't that set here?
InputStreamEntity reqEntity = new InputStreamEntity(
new FileInputStream(myFile), myFile.length());
I don't know if what I am doing is right or not, please help, thanks
Edit -
When I try to set the content-length myself using
httppost.setHeader("Content-Length", String.valueOf(myFile.length()));
it comes back with header already set.
Hence why it is commented out
In my case using
reqEntity.setChunked(false);
solved the problem.
You may want to use MultipartEntity and add parts using addPart methods with StringBody and InputStreamBody (or) FileBody
That sets the length of the content for the InputStreamEntity which is used locally when writing the data to the OutputStream. It doesn't set that value as a parameter for your request. You'll need to set that header yourself.

InputStreamBody in HttpMime 4.0.3 settings for content-length

I am trying to send a multi part formdata post through my java code. Can someone tell me how to set Content Length in the following?? There seem to be headers involved when we use InputStreamBody which implements the ContentDescriptor interface. Doing a getContentLength on the InputStreamBody gives me -1 after i add the content. I subclassed it to give contentLength the length of my byte array but am not sure if other headers required by ContentDescriptor will be set for a proper POST.
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(myURL);
ContentBody cb = new InputStreamBody(new ByteArrayInputStream(bytearray), myMimeType, filename);
//ContentBody cb = new ByteArrayBody(bytearray, myMimeType, filename);
MultipartEntity mpentity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
mpentity.addPart("key", new StringBody("SOME_KEY"));
mpentity.addPart("output", new StringBody("SOME_NAME"));
mpentity.addPart("content", cb);
httpPost.setEntity(mpentity);
HttpResponse response = httpclient.execute(httpPost);
HttpEntity resEntity = response.getEntity();
I'm the author of the ByteArrayBody class you have commented out.
I wrote it because I faced the same issue you did. The original Jira ticket is here: https://issues.apache.org/jira/browse/HTTPCLIENT-1014
So, since you already have a byte[], either upgrade HttpMime to the latest version, 4.1-beta1, which includes this class. Or copy the code from the Jira issue into your own project.
The ByteArrayBody class will do exactly what you need.

Categories

Resources