I'm trying to do a POST HTTP request on a HTTPS server with a self-signed certificate. My POST is multipart to allow to send a file (picture or anything else).
I'm still getting the following error:
Error:javax.net.ssl.SSLHandshakeException: Handshake failed:Handshake failed
Here is my source code:
URL url = new URL(PROTOCOL + "://" + host + "/file");
URI uri = new URI(PROTOCOL, null, url.getHost(), url.getPort(), URLEncoder.encode(url.getPath(), "UTF-8").replace("+", "%20").replace("%2F", "/"), url.getQuery(), null);
String authorizationHeader = Hawk.generateAuthorizationHeader(url, "POST", (int) (System.currentTimeMillis() / 1000), Hawk.generateNonce(), url.getPort());
HttpClient client = getHttpClient();
HttpPost httpPost = new HttpPost(uri);
httpPost.setHeader("Authorization", authorizationHeader);
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
java.io.File file = new java.io.File(fullLocalFilePath);
entityBuilder.addBinaryBody(fullLocalFilePath, file);
HttpEntity entity = entityBuilder.build();
httpPost.setEntity(entity);
HttpResponse response = client.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
httpEntity.consumeContent();
I have encountered something like this before, so here's my guess. The issue is that the certificate is using a different domain than where I'm currently using it. In OpenSSL, the domain name is the Common Name which it will ask you when creating the certificate, or if doing it as a parameter, it is the CN. The value of this should be the same as the domain of the server that you are trying to access.
You may try this:
For windows, go to %systemroot%\system32\drivers\etc, edit hosts as an administrator. Add a line something like this <your IP> mysampledomain.net, then when creating your SSL key/certificate, put mysampledomain.net as the value of the domain name i.e. Common Name in OpenSSL parameters. For linux, the procedure is the same, except that the hosts file is located in /etc/hosts.
Try invoking your code and see if you still get the same error.
Related
I would like the users of my Android app to be able to send zip files to my server using http. The use case I am imagining looks like this:
The user sends a zip file and a String containing a password using a HttpClient and HttpPost (as described here) to my server.
By logging in to www.example.com/my_app with existing password, users can download the files that the people have sent to my server under the given password.
I don't understand how to do the second step. What code do I need to write on my website to receive files that the Android users have been sending? I have a shared server under my hosting plan and a simple website.
You first need to modify the upload code(Since file upload is treated as multipart data).
Here is the modified upload code--
String url = "http://localhost/upload.php";
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),
"file.txt");
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
Part[] parts = new Part[1];
parts[0] = new FilePart("fileToUpload", file);
MultipartEntity reqEntity = new MultipartEntity(parts);
reqEntity.setContentType("binary/octet-stream");
reqEntity.setChunked(true); // Send in multiple parts if needed
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute(httppost);
} catch (Exception e) {
e.printStackTrace();
}
Here I have used the fileToUpload as the parameter key for uploaded file. On server code you can use the same key for your $_FILES["fileToUpload"].
Here is the simplest PHP code to accept the uploaded data from above android code--
<?php
$target_dir = "/Users/chauhan/Desktop/uploads/";
$target_file = $target_dir . basename("abc.txt");
move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file);
?>
I am trying to fetch current user info after making him log into his box, using the box sdk for android. In the box api documentation, they have mentioned everything using curls. I am not familiar with curl. So, can anyone please give me a java equivalent for this curl operation :
curl https://api.box.com/2.0/users/me-H "Authorization: Bearer ACCESS_TOKEN".
I have the users access token.So, please give me a java equivalent for the above curl operation.
You can use java HttpClient
HttpClient client = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(URL);
httpPost.setHeader("Authorization", "Bearer ACCESS_TOKEN"); // add headers if needded
//set params
BasicNameValuePair[] params = new BasicNameValuePair[] {new BasicNameValuePair("param1","param value"),
new BasicNameValuePair("param2","param value")};
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity( Arrays.asList(params), "utf-8");
httpPost.setEntity(urlEncodedFormEntity);
//execute request
HttpResponse response = client.execute(httpPost);
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity); //here response in string you can parse it
The HttpClient object that the other answer proposes is now deprecated. I solved a CURL problem like yours (with the extra difficulty of uploading a .wav file). Check out my code in this this answer/question. How to upload a WAV file using URLConnection
I have an app on GAE at: http://1.myawesomecity.appspot.com/
FIXED:
HttpPost post = new HttpPost("http://1.myawesomecity.appspot.com/");
http_client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
String result = EntityUtils.toString( http_client.execute(post).getEntity(), "UTF-8");
String actualURL = result.substring(result.indexOf("http://"), result.indexOf("\" method"));
Log.w("asdf", "url " + actualURL );
post = new HttpPost(actualURL);
http_client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
String mime_type = "image/png";
File file = new File( filename ); //context.getFilesDir(),
entity.addPart( "myFile", new FileBody( file, mime_type));
post.setEntity( entity );
String res = EntityUtils.toString( http_client.execute(post).getEntity(), "UTF-8");
Log.w("asdf", res);
The above grabs the ACTUAL upload URL from the GAE server, and passes in the file as dictated by the CORRECT answer below.
Old Question:
As you can see, if you choose a file and hit submit, it will 404, but the file actually does get stored (as long as it is not too big, < 100kb). Don't type in anything in the first text field.
Now, putting aside how this particular app is barely functional, I'm trying to upload a file from Android onto this server.
The site's upload script uses blobstore, and the file field's name is "myFile".
Now in my Android app, I have:
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(<my app's url>);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("myFile", <path to a file selected by user> ) );
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httpclient.execute(httppost);
This throws an exception.
How is this any different from me going to my site through a browser, choosing a file, and hitting submit? Why does going through a browser actually go through with uploading the file, when the Android code does not?
I know that my filepath is valid. Is there something I'm doing wrong? or is clicking on "submit" from a browser different from executing a httpclient from Android?
Uploading file to a blobstore on GAE is a two step process:
first you need to get a proper URL where to POST your data, usually people use something like "/bloburl" handler for that purpose
when you have blob upload URL, you use it in your request.
the file you send does not go as NameValuePair, it's supposed to go as a MultiPartEntity.
here's the code that works (you'll need apache http library for MultiPartEntry support):
DefaultHttpClient http_client = new DefaultHttpClient();
HttpGet http_get = new HttpGet(Config.BASE_URL + "bloburl");
HttpResponse response = http_client.execute(http_get);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String first_line = reader.readLine();
Log.w(TAG, "blob_url: " + first_line);
HttpPost post = new HttpPost(first_line);
http_client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
mime_type = "application/zip";
File file = new File( context.getFilesDir(), filename );
entity.addPart( "file", new FileBody( file, mime_type));
post.setEntity( entity );
String result = EntityUtils.toString( http_client.execute(post).getEntity(), "UTF-8");
Log.i(TAG, result);
I need to use httpclient to connect to a webpage (Apache) running PHP scripts which is protected with .htaccess authentication.
I've been reading questions and answers (in here and other places) for an hour now, and none of the sultions is working for me. Either the methods people are using in classes like Base64.java does not exist, or the parameters are wrong.
I'm connecting to normal (non-protected webpages like this):
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);
nameValuePairs.add(new BasicNameValuePair("date", cDate));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
But this, naturally, doesn't help when the page is protected. So how can I, in the easiest way, pass my username and password to the connection?
You can get a Base64 here: http://iharder.sourceforge.net/current/java/base64/.
I usually do something like following for authentication:
StringBuilder authentication = new StringBuilder().append("dogT4g").append(":").append("petTheDog5");
String result = Base64.encodeBytes(authentication.toString().getBytes());
httppost.setHeader("Authorization", "Basic " + result);
Hope that solves your problem.
As part of my Android app, I'd like to upload bitmaps to be remotely stored. I have simple HTTP GET and POST communication working perfectly, but documentation on how to do a multipart POST seems to be as rare as unicorns.
Furthermore, I'd like to transmit the image directly from memory, instead of working with a file. In the example code below, I'm getting a byte array from a file to be used later on with HttpClient and MultipartEntity.
File input = new File("climb.jpg");
byte[] data = new byte[(int)input.length()];
FileInputStream fis = new FileInputStream(input);
fis.read(data);
ByteArrayPartSource baps = new ByteArrayPartSource(input.getName(), data);
This all seems fairly clear to me, except that I can't for the life of me find out where to get this ByteArrayPartSource. I have linked to the httpclient and httpmime JAR files, but no dice. I hear that the package structure changed drastically between HttpClient 3.x and 4.x.
Is anyone using this ByteArrayPartSource in Android, and how did they import it?
After digging around in the documentation and scouring the Internet, I came up with something that fit my needs. To make a multipart request such as a form POST, the following code did the trick for me:
File input = new File("climb.jpg");
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://localhost:3000/routes");
MultipartEntity multi = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
String line;
multi.addPart("name", new StringBody("test"));
multi.addPart("grade", new StringBody("test"));
multi.addPart("quality", new StringBody("test"));
multi.addPart("latitude", new StringBody("40.74"));
multi.addPart("longitude", new StringBody("40.74"));
multi.addPart("photo", new FileBody(input));
post.setEntity(multi);
HttpResponse resp = client.execute(post);
The HTTPMultipartMode.BROWSER_COMPATIBLE bit is very important. Thanks to Radomir's blog on this one.
try this:
HttpClient httpClient = new DefaultHttpClient() ;
HttpPost httpPost = new HttpPost("http://example.com");
MultipartEntity entity = new MultipartEntity();
entity.addPart("file", new FileBody(file));
httpPost.setEntity(entity );
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
} catch (ClientProtocolException e) {
Log.e("ClientProtocolException : "+e, e.getMessage());
} catch (IOException e) {
Log.e("IOException : "+e, e.getMessage());
}
Perhaps you can do following step to import library into your Android.
requirement library
- apache-mime4j-0.6.jar
- httpmime-4.0.1.jar
Right click your project and click properties
select java build path
select tab called "Order and Export"
Apply it
Fully uninstall you apk file with the adb uninstall due to existing apk not cater for new library
install again your apk
run it
Thanks,
Jenz
I'm having the same problem. I'm trying to upload an image through MultiPart Entity and it seens that the several updates on HttpClient/MIME are cracking everything. I'm trying the following code, falling with an Error "NoClassDefFoundError":
public static void executeMultipartPost(File image, ArrayList<Cookie> cookies, String myUrlToPost) {
try {
// my post instance
HttpPost httppost = new HttpPost(myUrlToPost);
// setting cookies for the connection session
if (cookies != null && cookies.size() > 0) {
String cookieString = "";
for (int i=0; i<cookies.size(); ++i) {
cookieString += cookies.get(i).getName()+"="+cookies.get(i).getValue()+";";
}
cookieString += "domain=" + BaseUrl + "; " + "path=/";
httppost.addHeader("Cookie", cookieString);
}
// creating the http client
HttpClient httpclient = new DefaultHttpClient();
// creating the multientity part [ERROR OCCURS IN THIS BELLOW LINE]
MultipartEntity multipartEntity = new MultipartEntity();
multipartEntity.addPart("photoupload", new FileBody(image));
httppost.setEntity(multipartEntity);
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
} catch (Exception e) {}
}
This method is fully compilable and uses the httpclient-4.0.1.jar and httpmime-4.2.jar libs, but again, I remember that it crashs in the commented line for me.