POST two InputStreams in a javax Request - java

I'm trying to send a request to an endpoint that takes a form with two files. The method I'm currently trying fails on the last line:
WebTarget client = myUtils.createClient(URL, ENDPOINT);
MultivaluedMap<String, InputStream> formData = new MultivaluedHashMap<>();
formData.add(FILE_1, stream1);
formData.add(FILE_2, stream2);
Entity<MultivaluedMap<String, InputStream>> entity = Entity.entity(formData, MediaType.MULTIPART_FORM_DATA_TYPE);
Response response = client.request().post(entity);
The error reached is
javax.ws.rs.ProcessingException: RESTEASY003215: could not find writer for content-type multipart/form-data type: javax.ws.rs.core.MultivaluedHashMap
Changing MediaType to APPLICATION_FORM_URLENCODED_TYPE yields
java.lang.ClassCastException: java.io.SequenceInputStream cannot be cast to java.lang.String
Is there a better way to handle POSTing a form with two files?

There are multiple ways.
If you are using Jersey, One way is to do something like:
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
....
....
FileDataBodyPart fileDataBodyPart =
new FileDataBodyPart("file", new File("/filelocation/file.txt"));
FormDataMultiPart formDataMultiPart = (FormDataMultiPart)
FormDataMultiPart.field("somekey","somevalue")
.bodyPart( fileDataBodyPart);
WebTarget target = client.target(restServiceURLYouwant);
Response response = target.request().post(Entity.entity(formDataMultiPart,
formDataMultiPart.getMediaType()));
formDataMultiPart.close();
Another way is to use Apache HttpUtils
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
....
....
MultipartEntity multipartEntity = new MultipartEntity();
FileBody fb = new FileBody(file, "application/octet-stream");
multipartEntity.addPart(fb);
HttpClient httpClient = new DefaultHttpClient() ;
HttpPost httpPostRequest = new HttpPost (url) ;
//url above should be url of the Rest service endpoint
httpPostRequest.setEntity(multiPartEntity) ;
              
 HttpResponse response = httpClient.execute(httpPostRequest) ;

Related

slack api : files to upload to slack channel

I'm trying to publish image from my automation suite to slack channel.
URL to hit: https://slack.com/api/files.upload
Body is form-data type and it has,
file - image file upload
initial_comment - some string
channels - the slack channel to be published.
i tried using MultipartEntity class inside HttpPost
MultipartEntity multiPartEntity = new MultipartEntity();
FileBody fileBody = new FileBody(file);
//Prepare payload
multiPartEntity.addPart("file", fileBody);
multiPartEntity.addPart("file_type", new StringBody("JPG"));
multiPartEntity.addPart("initial_comment", new StringBody("cat shakes"));
multiPartEntity.addPart("channels", new StringBody("bot-e2e-report"));
//Set to request body
postRequest.setEntity(multiPartEntity);
Im getting the success response from http post. but the image is not posted in slack channel.any help!
The problem was with header. Actually, this slack api gives 200 response even for the wrong header. Working code:
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
//Set various attributes
MultipartEntityBuilder entitybuilder = MultipartEntityBuilder.create();
entitybuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entitybuilder.addBinaryBody("file", file);
entitybuilder.addTextBody("initial_comment", "cat");
entitybuilder.addTextBody("channels","bot-e2e-report");
HttpEntity mutiPartHttpEntity = entitybuilder.build();
RequestBuilder reqbuilder = RequestBuilder.post("https://slack.com/api/files.upload");
reqbuilder.setEntity(mutiPartHttpEntity);
//set Header
reqbuilder.addHeader("Authorization", "Bearer xoxb-16316687382-1220823299362-fdkBklPrY7rc72bQk3WSOSjD");
HttpUriRequest multipartRequest = reqbuilder.build();
// call post
HttpResponse response = httpclient.execute(multipartRequest);
// Parse the response
HttpEntity entity = response.getEntity();
String json = EntityUtils.toString(entity, StandardCharsets.UTF_8);
System.out.println(json);

How to use InputStream in Http setEntity?

I'm using org.apache.http.* and trying to PUT a file. I can do it with the below reference to the actual file, however, I'm looking for a way to do it by passing in an InputStream
File file = new File("/mytestfile.txt")
HttpPut request = new HttpPut("http://sharepointportal/site/mytestfile.txt");
request.setEntity(new FileEntity(file));
CloseableHttpResponse response = httpclient.execute(new HttpHost("sharepointportal"), request);
FileEntity doesn't seem to have a constructor that supports InputStream.
Question
How can I setEntity for HttpPut request with an InputStream?

Consuming soap service with NTLM Authentication

I am trying to consume a SOAP service with NTLM authentication by creating a NTLM engine (following instructions on http://hc.apache.org/httpcomponents-client-4.3.x/ntlm.html ) implemented AuthSchemeFactory and finally registered the AuthSchemeFactory to my HTTP Client. When I hit the service using my HTTP Client I get a reponse that "Status code - 415 , Message - The server cannot service the request because the media type is unsupported."
Can anybody tell how can I fix this issue of unsupported media to consume a NTLM-protected SOAP web service on Java platform. Is using JCIFS a correct option to conmsume NTLM protected service or are there any better approach(s). Thanks in advance.
DefaultHttpClient httpclient = new DefaultHttpClient();
httpclient.getAuthSchemes().register(AuthSchemes.NTLM,
new JCIFSNTLMSchemeFactory());
CredentialsProvider credsProvider = new BasicCredentialsProvider();
NTCredentials ntcred = new NTCredentials("USERNAME", "PASSWORD",
"HOST", "DOMAIN");
credsProvider.setCredentials(new AuthScope("HOST", 443,
AuthScope.ANY_REALM, "NTLM"), ntcred);
httpclient.setCredentialsProvider(credsProvider);
httpclient.getParams().setParameter(
CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
Writer writer = new StringWriter();
writer.write("MY SOAP REQUEST BODY");
HttpPost httppost = new HttpPost(
"https://<HOST_NAME>/XiPay30WS.asmx");
httppost.setEntity(new StringEntity(writer.toString()));
httppost.setHeader("Content-Type",
"application/x-www-form-urlencoded");
HttpResponse httpresponse = httpclient.execute(
new HttpHost("HOST", 443, "https"),
httppost, new BasicHttpContext());
String statusCode = httpresponse.getStatusCode();
If you use Spring WS support:
Check this Solution
http://dolszewski.com/spring/sharepoint-web-services-spring-and-ntlm-authentication/
#Bean("navisionMessageSender")
public HttpComponentsMessageSender httpComponentsMessageSender() {
HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
String user = env.getProperty("navision.endpoint.user");
String password = env.getProperty("navision.endpoint.password");
String domain = env.getProperty("navision.endpoint.domain");
NTCredentials credentials = new NTCredentials(user, String.valueOf(password), null, domain);
httpComponentsMessageSender.setCredentials(credentials);
return httpComponentsMessageSender;
}
Sample python implementation with NTLM Auth with FLASK.
If you want to use with java , run the standalone flask code below and call the url (e.g POST request /dora/httpWithNTLM ) from java code by http request
from flask import Flask, render_template, flash, request, url_for, redirect, session , Response
import requests,sys,json
from requests_ntlm import HttpNtlmAuth
app = Flask(__name__)
#app.route("/dora/httpWithNTLM",methods=['POST'])
def invokeHTTPReqWithNTLM():
url =""
reqData = json.loads(request.data)
reqxml=request.data
headers = {}
headers["SOAPAction"] = "";
headers["Content-Type"] = "text/xml"
headers["Accept"] = "text/xml"
print("req headers "+str(request.headers))
r = requests.Request("POST",url,auth=HttpNtlmAuth('domain\\username','password'), data=reqxml, headers=headers)
prepared = r.prepare()
s = requests.Session()
resp = s.send(prepared)
print (resp.status_code)
return Response(resp.text.replace("<","<").replace(">",">"),resp.status_code)
if __name__ == '__main__':
app.run(host="0.0.0.0",port=5001)

Java : Send Multipart File to RESTWebservice

I am using Spring as Technology. Apache HttpClient for calling Webservice. Basic purpose is to upload Multipart File(File is not any image file or video file). but Here My requirement is slightly different. Kindly check below image.
Here You can see first block. It is a simple GUI, having only 2 input tags along with proper form tag.
In second block, There is RESTFul Webservice, which takes Multipart File as parameter and process it. (Upto this it is done).
Now I am stuck here. I want to send this Multipart File to other RESTFul Webservice which consumes Multipart File only.
code Snippet of RESTFUL Webservice : (Commented some questions, need your suggestion)
#RequestMapping(value="/project/add")
public #ResponseBody String addURLListToQueue(
#RequestParam(value = "file") MultipartFile file,
#RequestParam(value = "id1", defaultValue = "notoken") String projectName,
#RequestParam(value = "id2", defaultValue = "notoken") String id2,
#RequestParam(value = "id3", defaultValue = "notoken") String id3){
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://localhost:8080/fs/project/add");
// 1) Do I need to convert it into File object? (tried but faced 400 Error)
// 2) Is there any provision to send Multipart File as it is?
MultipartEntity mpEntity = new MultipartEntity();
ContentBody cbFile = new FileBody(file, "multipart/form-data");
mpEntity.addPart("file", cbFile);
httppost.setEntity(mpEntity);
System.out.println("executing request " + httppost.getRequestLine());
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println(EntityUtils.toString(resEntity));
}
if (resEntity != null) {
resEntity.consumeContent();
}
httpclient.getConnectionManager().shutdown();
}
}
Questions : How to send Multipart File to RESTFul Webservice using HttpClient?
Can you check this file upload apache http client?
Also
HttpPost post = new HttpPost("http://echo.200please.com");
InputStream inputStream = new FileInputStream(zipFileName);
File file = new File(imageFileName);
String message = "This is a multipart post";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody
("upfile", file, ContentType.DEFAULT_BINARY, imageFileName);
builder.addBinaryBody
("upstream", inputStream, ContentType.create("application/zip"), zipFileName);
builder.addTextBody("text", message, ContentType.TEXT_PLAIN);
//
HttpEntity entity = builder.build();
post.setEntity(entity);
HttpResponse response = client.execute(post);
Source

How to POST JSON request using Apache HttpClient?

I have something like the following:
final String url = "http://example.com";
final HttpClient httpClient = new HttpClient();
final PostMethod postMethod = new PostMethod(url);
postMethod.addRequestHeader("Content-Type", "application/json");
postMethod.addParameters(new NameValuePair[]{
new NameValuePair("name", "value)
});
httpClient.executeMethod(httpMethod);
postMethod.getResponseBodyAsStream();
postMethod.releaseConnection();
It keeps coming back with a 500. The service provider says I need to send JSON. How is that done with Apache HttpClient 3.1+?
Apache HttpClient doesn't know anything about JSON, so you'll need to construct your JSON separately. To do so, I recommend checking out the simple JSON-java library from json.org. (If "JSON-java" doesn't suit you, json.org has a big list of libraries available in different languages.)
Once you've generated your JSON, you can use something like the code below to POST it
StringRequestEntity requestEntity = new StringRequestEntity(
JSON_STRING,
"application/json",
"UTF-8");
PostMethod postMethod = new PostMethod("http://example.com/action");
postMethod.setRequestEntity(requestEntity);
int statusCode = httpClient.executeMethod(postMethod);
Edit
Note - The above answer, as asked for in the question, applies to Apache HttpClient 3.1. However, to help anyone looking for an implementation against the latest Apache client:
StringEntity requestEntity = new StringEntity(
JSON_STRING,
ContentType.APPLICATION_JSON);
HttpPost postMethod = new HttpPost("http://example.com/action");
postMethod.setEntity(requestEntity);
HttpResponse rawResponse = httpclient.execute(postMethod);
For Apache HttpClient 4.5 or newer version:
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("http://targethost/login");
String JSON_STRING="";
HttpEntity stringEntity = new StringEntity(JSON_STRING,ContentType.APPLICATION_JSON);
httpPost.setEntity(stringEntity);
CloseableHttpResponse response2 = httpclient.execute(httpPost);
Note:
1 in order to make the code compile, both httpclient package and httpcore package should be imported.
2 try-catch block has been ommitted.
Reference:
appache official guide
the Commons HttpClient project is now end of life, and is no longer
being developed. It has been replaced by the Apache HttpComponents
project in its HttpClient and HttpCore modules
As mentioned in the excellent answer by janoside, you need to construct the JSON string and set it as a StringEntity.
To construct the JSON string, you can use any library or method you are comfortable with. Jackson library is one easy example:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.createObjectNode();
node.put("name", "value"); // repeat as needed
String JSON_STRING = node.toString();
postMethod.setEntity(new StringEntity(JSON_STRING, ContentType.APPLICATION_JSON));
I use JACKSON library to convert object to JSON and set the request body like below. Here is full example.
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost("https://jsonplaceholder.typicode.com/posts");
Post post = new Post("foo", "bar", 1);
ObjectWriter ow = new ObjectMapper().writer();
String strJson = ow.writeValueAsString(post);
System.out.println(strJson);
StringEntity strEntity = new StringEntity(strJson, ContentType.APPLICATION_JSON);
httpPost.setEntity(strEntity);
httpPost.setHeader("Content-type", "application/json");
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
System.out.println(response.getCode() + " " + response.getReasonPhrase());
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
System.out.println(result);
EntityUtils.consume(entity);
} catch (ParseException e) {
e.printStackTrace();
}
} catch (IOException e) {
System.out.println(e.getMessage());
}

Categories