I am using Apache HttpClient to download content from the server. I want to check the size before downloading content. I have used HTTPGet to download content and before processing the inputstream I am checking the content-length header but I see HTTPGet will download the body too even though we do not process.
var httpGet = httpGet(url);
try (final var closeableHttpResponse = closeableHttpClient.execute(httpGet);) {
final var statusCode = closeableHttpResponse.getStatusLine().getStatusCode();
final var headers = getHeadersMap(closeableHttpResponse.getAllHeaders());
final var contentLength = Long.valueOf(headers.get("content-length"));
final var entity = closeableHttpResponse.getEntity();
if (<<contentLength validation>>)) {
// Not to process
} else {
final var inputstream = entity.getContent();
// Processing inputstream
EntityUtils.consumeQuietly(entity);
}
} catch (IOException e) {
// Error Handling
}
If I use HTTP Head it will give only headers. Is it a correct approach to determining response size?
There are some cases in which the content-length header doesn't have length. Is there any other way too for determine size before downloading if the content-length header doesn't have a length?
Related
I am trying to implement the MOT history API https://dvsa.github.io/mot-history-api-documentation/ and they give an example using CURL which works with the supplied api key successfully when using an online CURL tool.
I am trying to implement this in Android and realise I have to use something like HttpPost rather than CURL, this is my code:
//Tried with full URL and by adding the registration as a header.
//HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration=" + reg_selected);
HttpPost httpPost = new HttpPost("https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests");
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("Accept", "application/json+v6");
httpPost.addHeader("x-api-key", "abcdefgh123456");
httpPost.addHeader("registration", reg_selected);
StringEntity entity = new StringEntity(jsonObj.toString(), HTTP.UTF_8);
httpPost.setEntity(entity);
HttpClient client = new DefaultHttpClient();
try {
HttpResponse response = client.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
InputStream inputStream = response.getEntity().getContent();
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String readLine = bufferedReader.readLine();
String jsonStr = readLine;
JSONObject myJsonObj = new JSONObject(jsonStr);
}else if (response.getStatusLine().getStatusCode() == 400){
//Bad Request Invalid data in the request. Check your URL and parameters
error_text = "Bad Request";
}else if (response.getStatusLine().getStatusCode() == 403){
//Unauthorised – The x-api-key is missing or invalid in the header
error_text = "Authentication error"; //<<<< FAILS HERE 403
}
response.getStatusLine().getStatusCode() returns • "403 – Unauthorised – The x-api-key is missing or invalid in the header".
However the x-api-key that I use works correctly with the online CURL test so the actual key is correct but how I am adding it to my android code request must be invalid or similar.
Can anyone throw any light as to the correct way to convert the CURL into Android java so that the server does not return 403?
Thanks
It's easy to do with Jsoup:
// CREATE CONNECTION
Connection conn=Jsoup.connect("URL_GOES_HERE");
// ADD POST/FORM DATA
conn.data("KEY", "VALUE");
// ADD HEADERS HERE
conn.header("KEY", "VALUE");
// SET METHOD AS POST
conn.method(Connection.Method.POST);
// ACCEPT RESPONDING CONTENT TYPE
conn.ignoreContentType(true);
try
{
// GET RESPONSE
String response = conn.execute().body();
// USE RESPONSE HERE
// CREATE JSON OBJECT OR ANYTHING...
} catch(HttpStatusException e)
{
int status = e.getStatusCode();
// HANDLE HTTP ERROR HERE
} catch (IOException e)
{
// HANDLE IO ERRORS HERE
}
Ps: I guess you are confused with Header and Post Data. The key etc (Credentials) must be used as Post Data and Content Type etc as Header.
I take back the program of a colleague.
He did the method (This program allows to upload a file on a server):
protected String uploadFile(File inputFile, String uuidFile) throws IOException,
ClientProtocolException {
HttpPost post = new HttpPost(new StringBuilder()
.append("http://xxxxxxxxxxxxx/FileServlet/").append("/uploadFile")
.toString());
post.addHeader("UuidFile", uuidFile);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("file", new FileBody(inputFile));
HttpEntity httpEntity = builder.build();
post.setEntity(httpEntity);
CloseableHttpClient client = HttpClients.createDefault();
HttpResponse response = null;
try {
response = client.execute(post);
if (response.getStatusLine().getStatusCode() == 200) {
Pattern p = Pattern.compile("File uploaded into (.*)</h2>");
String messageErreur = IOUtils.toString(response.getEntity().getContent());
System.out.println(messageErreur);
Matcher m = p.matcher(messageErreur);
if (m.find()) {
return m.group(1);
}
} else {
throw new RuntimeException(response.getStatusLine().getStatusCode() + ": " + new String(IOUtils.toByteArray(response.getEntity().getContent())));
}
return null;
} finally {
client.close();
}
}
The error in the console is
There was an error: the request was rejected because its size
(68142301) exceeds the configured maximum (52428800)
However I don't know how to augment the maximum size of the file uploaded...
Do you have an idea ?
Thanks,
Arnaud
To resolve the error as of now Check your web.xml for the below configuration in the servlet. Increase the size and check.
<multipart-config>
<max-file-size>68142301</max-file-size>
<max-request-size>68142301</max-request-size>
<file-size-threshold>0</file-size-threshold>
</multipart-config>
It functions, an other colleague gave project side serve, it had
ServletFileUpload upload = new ServletFileUpload(factory);
// sets maximum size of upload file
upload.setFileSizeMax(MAX_FILE_SIZE);
// sets maximum size of request (include file + form data)
upload.setSizeMax(MAX_REQUEST_SIZE);
to change
Is it possible to use the java URL.openStream() method to read the file into an input stream when the URL is a query string rather than a direct link to a file? E.g. the code I have is:
URL myURL = new URL("http://www.test.com/myFile.doc");
InputStream is = myURL.openStream();
This works fine for a direct file link. But what if the URL was http://www.test.com?file=myFile.doc ? Would I still be able to obtain the file stream from the server response?
Thanks!
Generally YES, it will work.
But note that URL.openStream() method doesn't follow redirects and not so agile with specifying some additional HTTP behaviours: request type, headers, etc.
I'd recommend to use Apache HTTP Client instead:
final CloseableHttpClient httpclient = HttpClients.createDefault();
final HttpGet request = new HttpGet("http://any-url");
try (CloseableHttpResponse response = httpclient.execute(request)) {
final int status = response.getStatusLine().getStatusCode();
if (status == 200) {
final InputStream is = response.getEntity().getContent();
} else {
throw new IOException("Got " + status + " from server!");
}
}
finally {
request.reset();
}
The URL class works for any url, including:
new URL("http://www.example.com/");
new URL("file://C/windows/system32/cmd.exe");
new URL("ftp://user:password#example.com/filename;type=i");
Its up to the application to do something with the data, for example download the data, or treat it as plain text.
I'm trying to call a webservice with my application, but I get no error, the URL is the good one and return something (via the browser), but I get no content.
try {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
int lenght = (int) entity.getContentLength();
is = entity.getContent();
} catch (Exception e) {
Log.e("log_tag", "Error in http connection" + e.toString());
}
lenght is equal to -1 due to the empty response he receives
Does the response from the url need to be HTML ? Or anything I output can be grab by the HttpClient ?
The response does not need to be HTML, but if the server side does not return a content-length header in the response, length will be negative.
The response does not necessarily need to be in HTML.
A negative value returned by getContentLength() means the content length is not returned by the server. It does not mean there is no content. It's possible to have content returned by the request, but still have a negative value returned by getContentLength().
You can still get the content returned by the request:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
entity.writeTo(baos);
String contentString = baos.toString();
I'm trying to use the API from Web Of Knowledge(WoK) to obtain some data. The documentation explain that you have to do POST Requests through HTTPS, sending a XML which contains the queries. But I only get the error 400 form server. (Bad Request)
Here is my code, I found it in Google and I make some fixes for my case.
public static void main(String[] args) throws Exception {
// Get target URL
String strURL = /*Here the Server URL*/;
// Get file to be posted
String strXMLFilename = "src/main/resources/xml/wosdata.xml";
File input = new File(strXMLFilename);
// Prepare HTTP post
PostMethod post = new PostMethod(strURL);
// Request content will be retrieved directly
// from the input stream
// Per default, the request content needs to be buffered
// in order to determine its length.
// Request body buffering can be avoided when
// content length is explicitly specified
post.setRequestEntity(new InputStreamRequestEntity(
new FileInputStream(input), input.length()));
// Specify content type and encoding
// If content encoding is not explicitly specified
// ISO-8859-1 is assumed
post.setRequestHeader(
"Content-type", "text/xml; charset=ISO-8859-1");
// Get HTTP client
HttpClient httpclient = new HttpClient();
// Execute request
try {
int result = httpclient.executeMethod(post);
// Display status code
System.out.println("Response status code: " + result);
// Display response
System.out.println("Response body: ");
System.out.println(post.getResponseBodyAsString());
}catch (Exception e) {
e.printStackTrace();
} finally {
// Release current connection to the connection pool
// once you are done
post.releaseConnection();
}
}
There is something wrong with the XML you are sending. You will have to look at server logs to find out exactly what, as 400 deliberately tells you as little as possible.
You should do it like this. First read the contents of the xml to String and do post using a StringRequestEntity.
// Get file to be posted
String strXMLFilename = "src/main/resources/xml/wosdata.xml";
StringBuilder contents = new StringBuilder();
try {
BufferedReader input = new BufferedReader(new FileReader(new File(strXMLFilename)));
try {
while (( line = input.readLine()) != null){
contents.append(line);
contents.append(System.getProperty("line.separator"));
}
}
finally {
input.close();
}
StringEntity requestEntity = new StringEntity(contents.toString());
post.setEntity(requestEntity);