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

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();

Related

How to POST NON-JSON request using Apache HttpClient?

I am to hitting an API which will return string data and as well I want to send data of string type(textfile in a paragraph).
You can use Apache httpcomponents, with http entities
Here is an example for sending a file in your POST request:
File file = new File("somefile.txt");
FileEntity entity = new FileEntity(file, ContentType.create("text/plain", "UTF-8"));
HttpPost httppost = new HttpPost("http://localhost/action.do");
httppost.setEntity(entity);
If you want a text content, you can use StringEntity:
StringEntity myEntity = new StringEntity("something", ContentType.create("text/plain", "UTF-8"));

How to get a complete file from mail attachment in java to send it through another APIs input?

I am creating an application where I need to get file attached in mail and then send that complete file as input of another API of portal called 'asana'. I don't want to save/ download the file locally.
I referred this site to get the attached file through mail.
But, I need to send the file to 'asana' API without downloading it.
Here is the code of asana API to send file through API.
String url = "https://app.asana.com/api/1.0/tasks/"+asanaActivitiesDto.getTaskId()+"/attachments";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
post.setHeader("Authorization", "Bearer " + asanaActivitiesDto.getBearerToken());
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("task", jsonInput.get("taskId").toString(), ContentType.TEXT_PLAIN);
// now here I actually want file from attachment of the mail
// currently taking file from local for testing
File f = new File(asanaActivitiesDto.getFile());
builder.addBinaryBody(
"file",
//Here, as a second input, I need to set file from the
//attachment of the mail
new FileInputStream(f),
ContentType.APPLICATION_OCTET_STREAM,
f.getName()
);
HttpEntity multipart = builder.build();
post.setEntity(multipart);
HttpResponse response = client.execute(post);
HttpEntity responseEntity = response.getEntity();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + post.getEntity());
System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
System.out.println(result.toString());
JSONParser parser = new JSONParser();
jsonOutput = (JSONObject) parser.parse(result.toString());
at the place of new FileInputStream(f), I need to send file attached to that mail. What are the possible ways to do the same?
You can just read the data in the email attachment as an InputStream. Try something like:
mbp = // the MimeBodyPart containing the attachment
builder.addBinaryBody(
"file",
mbp.getInputStream(),
ContentType.APPLICATION_OCTET_STREAM,
mbp.getFileName()
);

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.

Making an HttpRequest with MultipartEntity in it

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");

Categories

Resources