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.
I'm trying to connect to my server by HTTP and obtain a JSON object, but it seems that I can't do it.
Here's my code:
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class Conector {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpGet httpGet = new HttpGet("https://falseweb/select_all.php");
CloseableHttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println(response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
System.out.println(entity1.getContentEncoding());
EntityUtils.consume(entity1);
} finally {
response1.close();
}
} finally {
httpclient.close();
}
}
}
But instead of the JSON I get a printed null. I already tried the php file and it works, returning a json. Any idea what I'm doing wrong?.
The connection works because i got this message :
HTTP/1.1 200 OK
You seem to be logging out the content encoding as opposed to the actual content of the response which is probably why you aren't having any JSON joy.
Give the following a go (using Apache Commons IOUtils) :
System.out.println(IOUtils.toString(entity1.getContent(), "UTF8"));
If you can't use IOUtils then you can use any method of converting the InputStream into a String. More on that here.
I Have a webservice that uploads a file. (details in the first link)
To communicate with this webservice I use org.apache.http library (Apache HttpComponents). I have found most of this code if not all of it here.
Sadly the solution only works with images and despite the efforts when trying to upload a video is shows the error of Content Length too long. To try and fix this I decided to replace it with what's in current use. At first using HttpClientBuilder
HttpClient httpclient = HttpClientBuilder.create().disableContentCompression().build();
My try failed as it still gives the same error and after research I found out that I need to use the CloseableHttpClient as follow to disable the automatic headers
CloseableHttpClient httpclient = HttpClients.custom()
.setHttpProcessor(HttpProcessorBuilder.create().build())
.build();
That worked but when setting the headers something doesn't pass I can't figure it out. I did it as follow
httppost.addHeader("Keep-Alive", "timeout=5, max=100");
httppost.addHeader("Connection", "Keep-Alive");
httppost.addHeader("Content-Type", "text/html; charset=UTF-8");
But when tracing the response this is what I have
Http Client Builder Trace
Date,Tue, 28 Mar 2017 18:30:50 GMT
Server,Apache/2.4.23 (Win64) PHP/7.0.10
X-Powered-By,PHP/7.0.10
Content-Length,43
Keep-Alive,timeout=5, max=100
Connection,Keep-Alive
Content-Type,text/html; charset=UTF-8
Closable Response Trace
Date,Tue, 28 Mar 2017 18:31:27 GMT
Server,Apache/2.4.23 (Win64) PHP/7.0.10
Content-Length,311
Connection,close
Content-Type,text/html; charset=iso-8859-1
I tried to set the headers to the response but I am haven't figured how to instantiate it properly to set the headers. And also I am trying to understand why the httppost is not being taken in consideration. Did I miss something?
One last thing when I use Closable The way I did it doesn't upload anymore due to missing headers I guess.
EDIT
Error when uploading video
Exception in thread "main" org.apache.http.ContentTooLongException: Content length is too long: 16363535
at org.apache.http.entity.mime.MultipartFormEntity.getContent(MultipartFormEntity.java:103)
at org.apache.http.util.EntityUtils.toString(EntityUtils.java:199)
at org.apache.http.util.EntityUtils.toString(EntityUtils.java:306)
at testfileupload.PostFile.main(PostFile.java:100)
C:\Users\User\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)
EDIT
I changed the max file size for php following this but it still shows the same error
Update
This is how I handle the multipart (I use multipartform)
HttpEntity resEntity = MultipartEntityBuilder.create()
.addBinaryBody("userfile", file, ContentType.create("video/mp4"), file.getName())
.build();
I rememeber reading something about it (not sure) And as for the php.ini params that need to be of higher value upload_max_filesize = 40M and post_max_size = 40M and memory_limit = 128M which I am kinda sure its enough (using wamp64).
I kept trying to udnerstand the content length issue since ..
I found out that the HttpEntity sets calculates the length and I checked the value its 2 bits off I believe but no matter the conenction type it just doesn't work and sticks to content length error.
I also tried
HttpClient httpclient = HttpClients.custom().setDefaultHeaders(Arrays.asList(CustomHeader)).build();
But still nothing. At this point I highly doubt its about setting the header and more related to HttpEntity with the Multipart or the HttpPost but It could be else.
Upload
I tried with a 9s Video of a size ~350Kb but it still gives the content length error which means there might be a default content set or none at all
So I dont know what I did / changed but now its working with the error.
I would really want to know why this cause an error it doesn't make sense so far unless its calling something that can't take too high of a value (method of param type given value more than it can)
To be clear the error is generated when I use this (verifcation area)
System.out.println(response.getStatusLine());
if (resEntity != null) {
// error from below, kinda forgot about it
System.out.println(EntityUtils.toString(resEntity));
}
if (resEntity != null) {
// resEntity.consumeContent();
}
The webservice is the same as in the first link.
Below is my code (dont mind the comments I didn't clear the decrepated / changed / replaced / test / different approaches)
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpProcessorBuilder;
import org.apache.http.util.EntityUtils;
public class PostFile {
public static void main(String[] args) throws Exception {
// HttpClient httpclient = new DefaultHttpClient();
// CloseableHttpClient httpclient = HttpClients.custom()
// .setHttpProcessor(HttpProcessorBuilder.create().build())
// .build();
// Header headerCustom = new BasicHeader(HttpHeaders.CONTENT_LENGTH, "15");
// HttpClient httpclient = HttpClients.custom().build();
// HttpClient httpclient = HttpClientBuilder.create().disableContentCompression().build();
HttpClient httpclient = HttpClientBuilder.create().build();
// httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://localhost/userVids/upload.php");
httppost.setProtocolVersion(new ProtocolVersion("HTTP", 1, 1));
File file = new File("C:/Users/User/Desktop/test_video.mp4");
// httppost.addHeader("Content-Length", String.valueOf(file.length()));
// MultipartEntity mpEntity = new MultipartEntity();
// ContentBody cbFile = new FileBody(file, ContentType.MULTIPART_FORM_DATA);
// mpEntity.addPart("userfile", cbFile);
// System.out.println(mpEntity.getContentLength());
//
// httppost.setEntity(mpEntity);
/*
Date,Tue, 28 Mar 2017 18:30:50 GMT
Server,Apache/2.4.23 (Win64) PHP/7.0.10
X-Powered-By,PHP/7.0.10
Content-Length,43
Keep-Alive,timeout=5, max=100
Connection,Keep-Alive
Content-Type,text/html; charset=UTF-8
*/
/*
Date,Tue, 28 Mar 2017 18:31:27 GMT
Server,Apache/2.4.23 (Win64) PHP/7.0.10
Content-Length,311
Connection,close
Content-Type,text/html; charset=iso-8859-1
*/
HttpEntity resEntity = MultipartEntityBuilder.create()
.addBinaryBody("userfile", file, ContentType.create("video/mp4"), file.getName())
.build();
System.out.println("Entity Length " + resEntity.getContentLength());
// httppost.addHeader("Keep-Alive", "timeout=5, max=100");
// httppost.addHeader("Connection", "Keep-Alive");
// httppost.addHeader("Content-Type", "text/html; charset=UTF-8");
// httppost.addHeader("Content-Disposition", "form-data; name=\"userfile\"; filename=\"star_empty.png\"");
// httppost.addHeader("Content-Type", "image/png");
// httppost.addHeader("Content-Transfer-Encoding", "binary");
// httppost.addHeader("Content-Length", "99999");
httppost.setEntity(resEntity);
System.out.println("executing request " + httppost.getRequestLine());
HttpResponse response = httpclient.execute(httppost);
// HttpEntity resEntity = response.getEntity();
System.out.println("Headers (name,value)");
List<Header> httpHeaders = Arrays.asList(response.getAllHeaders());
httpHeaders.forEach((header) -> {
System.out.println(header.getName() + "," + header.getValue());
});
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println(EntityUtils.toString(resEntity));
}
if (resEntity != null) {
// resEntity.consumeContent();
}
// httpclient.getConnectionManager().shutdown();
}
}
BUT A HUGE NOTICE I had my php.ini (changed all of them in wamp didn't know if it would consider only the running version or reads all (didn't test) ) and changed the values as Lucas Holt (he fixed it i.e, I am just providing for who needs or maybe explanation) said and he deserves credit for it. (I am sure it didn't work before that I just tested a lot and dont remember really.)
I am trying to use some code that I got from a website that has sports data served publically via an API (http://developer.fantasydata.com).
The site provide some sample JAVA code to make the http request. For some reason the setEntity method for the declared request (request) is showing a "cannot find symbol error.
package epl.fixtures.test.app;
import java.net.URI;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class EPLFixturesTestApp {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
HttpClient httpclient = HttpClients.createDefault();
try
{
URIBuilder builder = new URIBuilder("https://api.fantasydata.net/soccer/v2/json/CompetitionDetails/EPL");
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
request.setHeader("Ocp-Apim-Subscription-Key", "****************");
// Request body
StringEntity reqEntity = new StringEntity("{body}");
request.setEntity(reqEntity);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null)
{
System.out.println(EntityUtils.toString(entity));
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
The line causing the issue is the request.setEntity(reqEntity); line
Can anyone explain this to me please? I have all the relevant jar files from apache added to the project libraries directory.
Thanks
HttpGet does not have a setEntity method.
This makes sense, since the request body has no meaning in GET requests.
Only classes implementing HttpEntityEnclosingRequest have this method.
I don't know why the documentation uses it, but it seems to work when omitting those two lines (which look meaningless anyway). Code:
URIBuilder builder = new URIBuilder("https://api.fantasydata.net/soccer/v2/json/CompetitionDetails/EPL");
URI uri = builder.build();
HttpGet request = new HttpGet(uri);
request.setHeader("Ocp-Apim-Subscription-Key", "****************");
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null)
{
System.out.println(EntityUtils.toString(entity));
}
So I use apache HttpComponents to handle http request in java.
Now I want to reuse the DefaultHttpClient, what should be possible accoarding to this example: http://wiki.apache.org/HttpComponents/QuickStart. The example itselfs give a ssl error so I modefied and simplefied it a bit. Now I always get a org.apache.http.client.ClientProtocolException
Here is my example program, basicly I just request 2 webpages using the same DefaultHttpClient.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class ClientFormLogin {
public static void main(String[] args) throws Exception {
DefaultHttpClient httpclient = new DefaultHttpClient();
//Handle first request.
HttpGet httpget = new HttpGet("http://tweakers.net/nieuws/82969/amazon-nederland-opent-digitale-deuren-in-september.html");
HttpResponse response = httpclient.execute(httpget);
System.out.println("Execute finished");
HttpEntity entity = response.getEntity();
String page = readInput(entity.getContent());
System.out.println("Request one finished without problems!");
//Handle second request
HttpGet httpost = new HttpGet("http://gathering.tweakers.net/forum/list_messages/1506977/last");
response = httpclient.execute(httpost);
entity = response.getEntity();
page = readInput(entity.getContent());
System.out.println("Request two finished without problems!");
}
private static String readInput(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte bytes[] = new byte[1024];
int n = in.read(bytes);
while (n != -1) {
out.write(bytes, 0, n);
n = in.read(bytes);
}
return new String(out.toString());
}
}
When runnig my example I get the folowing error
Request one finished without problems!
Exception in thread "main" org.apache.http.client.ClientProtocolException
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:909)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
at ClientFormLogin.main(ClientFormLogin.java:29)
Caused by: org.apache.http.HttpException: Unable to establish route: planned = {}->http://gathering.tweakers.net; current = {}->http://tweakers.net
at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:842)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:645)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:480)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
... 3 more
Any one can give me some pointers how I can solve this problem, except use a new DefaultHttpClient for every request.
Edit
I just found out if I stay on the same domain I have no problems so:
page1: 'http://tweakers.net/nieuws/82969/amazon-nederland-opent-digitale-deuren-in-september.html'
page2: 'http://tweakers.net/nieuws/82973/website-nujij-belandt-op-zwarte-lijst-google-door-malware.html'
I have no problems if I got to:
page1: 'http://tweakers.net/nieuws/82969/amazon-nederland-opent-digitale-deuren-in-september.html'
page2: 'http://gathering.tweakers.net/forum/list_messages/1506076/last'
I get the error.
Ofc I see this one minute after posting my question. Except if someone can tell me how I can go 2 sperate domains with the same DefaultHttpClient my question is already answered.
This is likely due to a recent bug in the v4.2 BasicClientConnectionManager affecting cross site redirects. See http://issues.apache.org/jira/browse/HTTPCLIENT-1193.
According to the maintainer, one temporary workaround is to use SingleClientConnManager or PoolingClientConnectionManager. Perhaps something like this:
ClientConnectionManager connManager = new PoolingClientConnectionManager();
DefaultHttpClient httpclient = new DefaultHttpClient(connManager);
...