Generate mixed/multipart HTTP request in Java - java

I would like to POST (in Java) a multipart/mixed request, where one part is of type 'application/json' and the other of type 'application/pdf'. Does anyone know of a library which will allow me to do this easily? Surprisingly I haven't been able to find one.
I'll generate the JSON, but I need to be able to set the content type of that part to 'application/json'.
Many thanks,
Daniel

Easy, use the Apache Http-client library (this code used version 4.1 and the jars httpclient, httpcore and httpmime), here's a sample:
package com.officedrop.uploader;
import java.io.File;
import java.net.URL;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
public class SampleUploader {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
String basePath = "http://localhost/";
URL url = new URL( basePath );
HttpHost targetHost = new HttpHost( url.getHost(), url.getPort(), url.getProtocol() );
HttpPost httpost = new HttpPost( String.format( "%s%s", basePath, "ze/api/documents.xml"));
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("file_1", new FileBody( new File( "path-to-file.pdf" ) , "file.pdf", "application/pdf", null));
entity.addPart("uploaded_data_1", new FileBody( new File( "path-to-file.json" ) , "file.json", "application/json", null));
httpost.setEntity(entity);
HttpResponse response = httpclient.execute( targetHost, httpost);
}
}

Related

How to fix "Early EOF" error from java http post of a file?

I'm trying to post a file to a rest API and the code I'm using gives an "Early EOF" error. I've looked around and most of what I'm seeing seems to suggest that the data send doesn't match the expected size of what is being sent.
How do I fix this?
Code is shown below:
(based on How can I make a multipart/form-data POST request using Java?)
import java.io.File;
import java.io.FileInputStream;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import lombok.extern.slf4j.Slf4j;
#Slf4j
public class HttpFileUpload {
public static void main(String[] args) throws Exception {
log.info("Starting...");
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("https://url-to-rest-api/api/2.0/dbfs/put");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("path", "/FileStore/my-dir/myfilename.txt", ContentType.TEXT_PLAIN);
String token = "my-security-token";
// This attaches the file to the POST:
File f = new File("C:\\path-to\\my-file.txt");
builder.addBinaryBody(
"file",
new FileInputStream(f),
ContentType.APPLICATION_OCTET_STREAM,
f.getName());
HttpEntity multipart = builder.build();
uploadFile.addHeader("Authorization", "Bearer " + token);
uploadFile.setEntity(multipart);
log.info("Starting upload");
CloseableHttpResponse response = httpClient.execute(uploadFile);
log.info("Done with upload");
HttpEntity responseEntity = response.getEntity();
log.info("Got response");
log.info("Done.");
}
}
This turned out to be a timeout issue. The api I was writing to timed out the request and generated the EOF exception. The api had another call that allowed the file to be uploaded in segments so I modified my solution to use this call instead of trying to upload the entire file in one call.

Able to hit in postman but not in java

I am not able to get a response from eclipse when integrated in java code. I am able to retrieve the response from postman/insomnia, but not from eclipse. I masked the token and the URL in this image.
My current code is:
public class Test{
public static void main(String[] args) throws ParseException, IOException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
httppost.addHeader("Authorization", "Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
httppost.addHeader("Accept", "*/*");
httppost.addHeader("Content-type", "multipart/form-data; boundary=X-INSOMNIA-BOUNDARY");
httppost.addHeader("Host","process-workorders-mti64mke4a-uc.a.run.app");
File fileToUse = new File("D:\\firstImage.jpg"); // this is the image I am uoploadin
FileBody data = new FileBody(fileToUse);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("mode", new StringBody("api"));
reqEntity.addPart("file", data);
*// seems there is issue here in passing form parameters*
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
System.out.println( response ) ;
HttpEntity resEntity = response.getEntity();
System.out.println( resEntity ) ;
System.out.println( EntityUtils.toString(resEntity) );
EntityUtils.consume(resEntity);
httpclient.getConnectionManager().shutdown();
}
}
Below are the imports:
import java.io.File;
import java.io.IOException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
Tried OKHTTPClient and it worked

How to avoid URIBuilder to encode comma to "%2C" or other characters in query params

I would like to create a URI using apache class org.apache.http.client.utils.URIBuilder and I need to not encode query params to percent-encoding.
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
RequestConfig config = RequestConfig.custom().build();
HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(config);
// URI url = new URI("http://some-website.com/?range=10,20");
// If url is created with the line above the comma "," is not encoded when sending the request
// When you use URIBuilder the comma "," is converted to "%2C"
URIBuilder uribuilder = new URIBuilder("http://some-website.com/");
uribuilder.addParameter("range", "10,20");
URI url = uribuilder.build();
System.out.println("URL => " + url.toString());
HttpHost targetHost = new HttpHost(url.getHost(), url.getPort(), url.getScheme());
HttpClient client = builder.build();
HttpRequestBase req = new HttpPost(url);
HttpResponse httpResponse = client.execute(targetHost, req);
HttpEntity entity = httpResponse.getEntity();
String responseString = EntityUtils.toString(entity, "UTF-8");
System.out.println(responseString);
System.out.println("Finished");
}
}
Is there a way to do that using the URIBuilder class like some flag I don't know?
I would appreciate other suggests (maybe better ways than my code) to accomplish this. But I can't send the characters in query string encoded.
Thanks in advance.

java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.<init>(I)V

I have to connect to a URL, and in that i have a link click here to download, when i click on it,it downloads a zip file which has multiple files in it. My requirement is to download that zip file using java application.I am trying to point to a URl and download the file.
I have taken the code from How to remotely login to a Jenkins server using Java?
Below is the code:
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.net.URI;
public class JenkinsScraper {
public String scrape(String urlString, String username, String password) throws ClientProtocolException, IOException {
URI uri = URI.create(urlString);
HttpHost host = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(uri.getHost(), uri.getPort()), new UsernamePasswordCredentials(username, password));
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(host, basicAuth);
CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
HttpGet httpGet = new HttpGet(uri);
// Add AuthCache to the execution context
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
HttpResponse response = httpClient.execute(host, httpGet, localContext);
return EntityUtils.toString(response.getEntity());
}
public static void main(String args[]) throws IOException {
JenkinsScraper obj = new JenkinsScraper();
String result = obj.scrape("https://info-build.gm.com/view/tools/job/MISC.DefectSummaryReport/lastSuccessfulBuild/artifact/","JZYH8B","may#2017");
System.out.print("result :: " + result);
}
}
I'm facing below exception:
Exception in thread "main" java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.<init>(I)V
at org.apache.http.impl.auth.BasicScheme.authenticate(BasicScheme.java:168)
Had someone worked on this type of requirement where we will have a link in the Jenkins URL, using java code we need to hit the URL and download the zip file.Do i need tp use any other API to achieve this functionality.Any suggestions would be helpful.

Connect to Dynamic CRM using Java Http Client

I have been trying to connect to CRM using the below Java code, but I am getting an authentication issue.
package com.raj;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.NTCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
public class MSDynaOData {
/**
* #param args
*/
public static void main(String[] args) throws ClientProtocolException, IOException {
DefaultHttpClient httpclient = new DefaultHttpClient();
NTCredentials creds = new NTCredentials("XXXXXXXXXX", "XXXXXXX", "", "");
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpHost target = new HttpHost("XXXXXXXXX", 80, "http");
HttpContext localContext = new BasicHttpContext();
// Execute a cheap method first. This will trigger NTLM authentication
String url = "/XRMServices/2011/Organization.svc/Account";
url += "?$select=Name";
HttpGet httpget = new HttpGet(url);
httpget.addHeader("Accept", "application/json");
HttpResponse response = httpclient.execute(target, httpget, localContext);
HttpEntity entity = response.getEntity();
System.out.println(" Status :: " + response.getStatusLine());
for (Header header : response.getAllHeaders()) {
System.out.println(header.getName() + " : " + header.getValue());
}
System.out.println(IOUtils.toString(entity.getContent()));
}
}
Response contains :
Constants.TokenizedStringMsgs.GENERIC_ERROR = "<H1>Sorry, but we're having trouble signing you in</H1><p>Please try again in a few minutes. If this doesn't work, you might want to contact your admin and report the following error: #~#ErrorCode#~#.</p>";
Constants.TokenizedStringMsgs.UPN_DISAMBIGUATE_MESSAGE = "It looks like #~#MemberName_LS#~# is used with more than one account. Which account do you want to use?";
I am able to login to CRM 2011 online through the credentials used in Java code successfully, but when I used same credentials in the code I am getting the above login issue response.
Please let me know if I am missing anything in the above code.

Categories