Howto do a simple ftp get file on Android - android

I can't find an example of a simple FTP access of a file anywhere, and the FTPClient class (which a couple of examples use) doesn't appear in the Android Class Index. I've got http access working, but how do I do a simple FTP get? All I want to do is download (for example):
ftp://tgftp.nws.noaa.gov/data/observations/metar/stations/KABQ.TXT
It shouldn't require login, change directory, etc.
Just giving that URL to the http access methods don't seem to work.
This is similar to the question at:
unable to read file from ftp in android?
I tried a simple:
StringBuilder response = new StringBuilder();
URLConnection ftpConn;
try {
URL netUrl = new URL("ftp://tgftp.nws.noaa.gov/data/observations/metar/stations/KABQ.TXT");
ftpConn = netUrl.openConnection();
BufferedInputStream bufRd = new BufferedInputStream(ftpConn.getInputStream());
int temp;
while ((temp = bufRd.read()) != -1) {
response.append(temp);
}
bufRd.close();
} catch (Exception e) {
return "Failure";
}
but it gets an exception on getInputStream:
Unable to connect to server: Unable to configure data port
Also, there must be a more intelligent way to pull the data out of the stream buffer than byte-by-byte, isn't there? I can't find that either.
Lastly, I need to do both http and ftp access, is there any reason not to use URLConnection for both access types? or is it better to use HttpConnection for http and URLConnection for ftp?
Thanks!

Whew! I finally got it going. I gave up on the simple way that works in webOS and WPF/C# where you can just do a ftp:://... you have to use the FTPClient package.
After fixing the library access (Project | Properties | Java Build Path | Libraries | Add JARs...) I fiddled with the calls until it started working. Here's the sequence of my FTPClient calls. It wouldn't work until I set it in passive mode.
mFTPClient = new FTPClient();
mFTPClient.connect("tgftp.nws.noaa.gov");
mFTPClient.login("anonymous","nobody");
mFTPClient.enterLocalPassiveMode();
mFTPClient.changeWorkingDirectory("/data/forecasts/taf/stations");
InputStream inStream = mFTPClient.retrieveFileStream("KABQ.TXT");
InputStreamReader isr = new InputStreamReader(inStream, "UTF8");

And I also found on the web someplace an answer to the 'byte-by-byte' question. This seems to work to convert an InputStream type directly to String type:
String theStr = new Scanner(inStream).useDelimiter("\\A").next();

I also looked for a simple ftp download example without using of 3rd party libs. Didn't find any, so post my solution here.
URLConnection by default uses user name 'anonymous' with empty password which is not accepted by many ftp servers, as they require e-mail as the password for 'anonymous'.
To use the following code in your app, just add try..catch and make sure that reading from stream isn't block UI thread.
URL url = new URL("ftp://ftp.mozilla.org/README");
URLConnection cn = url.openConnection();
cn.setRequestProperty ("Authorization", "Basic " + Base64.encodeToString("anonymous:a#b.c".getBytes(), Base64.DEFAULT));
final File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
FileOutputStream fos = new FileOutputStream(dir.getPath() + "/README");
InputStream is = cn.getInputStream();
int bytesRead = -1;
byte[] buf = new byte[8096];
while ((bytesRead = is.read(buf)) != -1) {
fos.write(buf, 0, bytesRead);
}
if(is != null)is.close();
if(fos != null){ fos.flush(); fos.close(); }
Hope this will save you some time.

Related

Is it possible to post at the same time a string and an image to a webserver?

There is a string variable and an image photo taken from the camera intent. The directory location of the photo is known. I want to make a HTTP post of the string variable and the image photo to a webserver at the same time. Is that possible ? If so , how to do it ?
From what I understand, you need to send an image and a string to your webserver within a single POST request. Here's how you'd proceed.
You first need to Base64 encode your image.
Start by converting your image into a byte array:
InputStream image = new FileInputStream(<path_to_image>);
byte[] buff = new byte[8192];
int readBytes;
ByteArrayOutputStream byteArrOS = new ByteArrayOutputStream();
try {
while ( (readBytes = inputStream.read(buff) ) != -1) {
byteArrOS.write(buff, 0, readBytes);
}
} catch (IOException e) {
e.printStackTrace();
}
byte[] b = byteArrOS.toByteArray();
Then convert it to Base64:
String bsfEncodedImage = Base64.encodeToString(b, Base64.DEFAULT);
Then build a query with the the string and the resulting Base64 both encoded with URLEncoder and "utf-8":
strImgQuery = "str="+URLEncoder.encode(<string_data>, "utf-8")+"&image="+URLEncoder.encode(bsfEncodedImage, "utf-8");
Declare a new URL:
URL postUrl = new URL("http://<IP>/postreq");
Open the connection:
HttpURLConnection conn = (HttpURLConnection)postUrl.openConnection();
Set output to "true" (needed for a POST request but not for GET):
conn.setDoOutput(true);
Set the request method to POST:
conn.setRequestMethod("POST");
The timeout:
conn.setReadTimeout(1e4);
Buffer the output to the output stream and flush/run:
Writer buffWriter = new OutputStreamWriter(conn.getOutputStream());
buffWrite.write(strImgQuery);
buffWriter.flush();
buffWriter.close();
At server side you'll get the str and image POST params which is dependent on your server implementation.
Note that your url must follow the URL Specification, otherwise you'll get a MalformedURLException. If that's the case, be sure to check what exactly the issue is. For example if you use a non-existing ttp "protocol" instead of http your exception will look something like this:
java.net.MalformedURLException: unknown protocol: ttp
at java.net.URL.<init>(URL.java:592)
at java.net.URL.<init>(URL.java:482)
at java.net.URL.<init>(URL.java:431)
at com.pheromix.core.lang.NumberFormatExceptionExample.MalformedURLExceptionExample.sendGetRequest(MalformedURLExceptionExample.java:28)
at com.pheromix.core.lang.NumberFormatExceptionExample.MalformedURLExceptionExample.main(MalformedURLExceptionExample.java:17)
Also, this is a synchronous operation and is ran on the UI thread. It might be costly or it might not depending on other operations you're already running and the size of the POST data. If the problem arises, run the job on another thread.
You can use URLEncoder
String strUrl = "http://192.168.1.9/impots/" +URLEncoder.encode("outil.php?action=OutilImporterDonneesMobile", "utf-8");
URL url = new URL(strUrl);

How to correctly download a file (zip in my case) through https in Android?

I was first using HttpURLConnection with my first test. Now I would like to also support https, but it doesn't work. I've been at it all day and so far nothing. Most of the past problems have been related to certificate issues. Weird thing is in my case it downloads the file, but its either corrupted (if its a simple file), or the zips contents are missing (empty). I will post my code to see if maybe I am doing something wrong.
try{
URL url = new URL(stuffs[0]);//<-actual url I am searching https://...
String fileName = stuffs[1];
String optionalFilePath = stuffs[2] == null ? null : stuffs[2];
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(20000);
connection.connect();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
checkErrorCode(connection.getResponseCode());
return false;
}
InputStream in = new BufferedInputStream(connection.getInputStream());
FileOutputStream out = null;
if(optionalFilePath == null)
out = new FileOutputStream(PATH +"/"+fileName);
else {
File newDir = new File(PATH+optionalFilePath);
newDir.mkdirs();
out = new FileOutputStream(PATH + (optionalFilePath==null?"":optionalFilePath) +"/"+fileName);
}
byte[] buffer = new byte[1024];
int count;
while((count = in.read(buffer)) != -1){
out.write(buffer, 0, count);
}
out.flush();
out.close();
in.close();
}
Upon further debugging, I found out the content length is -1. So I guess it makes sense why the zip is empty. Now I am not too sure why it returns -1. I download it on a web browser correctly. So I know it exists.
To Download file via https You should accept https certificate from application Trusting all certificates using HttpClient over HTTPS
And https file download in android causing exception
For Downlod zip or any check this out
Download a file with Android, and showing the progress in a ProgressDialog
I believe the answer is that you are calling connect().
URL url = new URL(stuffs[0]);//<-actual url I am searching https://...
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(20000);
connection.connect();
if(connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
checkErrorCode(connection.getResponseCode());
return false;
}
InputStream in = new BufferedInputStream(connection.getInputStream());
Try not calling connection.connect, and moving the response code check after the line that calls connection.getInputStream().

é=é: need to show as it is

I am getting some response from server in text format, it's working fine but in some cases i didn't get string as it is.
Explanation:- My db have one name like cupcaké but when i parse data it's show me cupcaké. I want to show as it is like cupcaké.
I tried URL.Encode and URL.Decode function with the help of utf-8 but none of them helpful. I need universal solution which work for all special character not only for this character.
Here is my jsonparser class, can i need to make changes in this file? or somewhere?
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
URL url = new URL(str);
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
json = jsonResults.toString();
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error processing Places API URL", e);
How can i show as it is on my screen?
Please give me any reference or hint.
After a long search, I found a good answer. These are html entities and can be shown by using the following code:
Html.fromHtml(Html.fromHtml((String) yourstring).toString());
Now every html entity's converted into the actual string. You can find more details here.
You need to work on Sms Encoding Concept .
Try some refrence:
http://www.codeproject.com/Tips/470755/Encoding-Decoding-7-bit-User-Data-for-SMS-PDU-PDU
Note that when you typed cupcaké in your question (before I edited it), the browser displayed it as cupcaké (here it is again, check the answer source: cupcaké). These are "html entities", and you can ask your favorite programming language to decode them into the corresponding character. In php, you'd use html_entity_decode().

Creating a playlist with Youtube DATA API on Android

I am trying to use the Youtube GDATA API in order to add a new playlist to a youtube account.
I base my code on the documentation: https://developers.google.com/youtube/2.0/developers_guide_protocol_playlists#Adding_a_playlist
I first get an access token and use my developer key appropriately.
The post seems to work just fine, but when trying to get back the response, I get a file not found exception while calling getInputStream.
Does anyone has an idea?
Thanks
Here is the connection code (an updated cleaner version):
#Override
protected Boolean doInBackground(Void... arg0) {
BufferedReader input = null;
InputStreamReader inputStreamReader = null;
StringBuilder postContentXml = new StringBuilder();
postContentXml.append("<?xml version='1.0' encoding='UTF-8'?>").
append("<entry xmlns='http://www.w3.org/2005/Atom'") .
append(" xmlns:yt='http://gdata.youtube.com/schemas/2007'>").
append("<title type='text'>Sports Highlights Playlist</title>").
append("<summary>A selection of sports highlights</summary>").
append("</entry>");
byte[] buffer = postContentXml.toString().getBytes();
StringBuilder response = new StringBuilder();
try {
URL url = new URL("https://gdata.youtube.com/feeds/api/users/default/playlists");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
// Initialize connection parameters
urlConnection.setConnectTimeout(30000);
urlConnection.setReadTimeout(30000);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
// Headers initialization
urlConnection.setRequestProperty("Content-Type", "application/atom+xml");
urlConnection.setRequestProperty("Content-Length", String.valueOf(buffer.length));
urlConnection.setRequestProperty("Authorization", mAuthToken);
urlConnection.setRequestProperty("GData-Version", "2");
urlConnection.setRequestProperty("X-GData-Key", YoutubeUtils.getDevKey());
OutputStream os = urlConnection.getOutputStream();
os.write(buffer, 0, buffer.length);
os.flush();
os.close();
InputStream inputStream = urlConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
input = new BufferedReader(inputStreamReader, 4096);
String strLine = null;
while ((strLine = input.readLine()) != null) {
response.append(strLine);
}
input.close();
inputStreamReader.close();
inputStream.close();
urlConnection.disconnect();
Log.d("CreatePlaylistTask", "Response: " + response);
}
catch(Exception e) {
Log.d("CreatePlaylistTask", "Error occured: " + e.getMessage());
}
return true;
}
I'm assuming that the POST wasn't actually successful.
If I had to guess from looking at your code, I'd think that the problem might be the Authorization header value. What does myAuthToken look like, and what type of token is it? If it's an OAuth 2 token, for instance, then the value needs to be Bearer TOKEN_VALUE, not just TOKEN_VALUE.
Also, please note that v3 of the YouTube Data API will be released in the near future, and it will offer better support on Android using the new Google APIs Client Library for Java.
I have put together a sample Android application which uses the YouTube Data v3 API to demonstrate how you can load a playlist into a ListView.
https://github.com/akoscz/YouTubePlaylist
Note that you MUST have a valid API key for this sample application to work. You can register your application with the Google Developer Console and enable the YouTube Data API. You need to Register a Web Application NOT an Android application, because the API key that this sample app uses is the "Browser Key".

Loading images from res or assets when web page in webview loads from server

I want to send down a webpage from a server to WebView components on Android handsets.
I've already learned how to enable the webpage to talk to the JavaScript handler, so the native application can interact with the webpage.
I am, however, stuck on images.
I want the webpage that comes from a server to somehow tell the app which image (stored in either res or in assets) to load. This way I don't have to send the image over the wire as well. Is this doable? It will make the process of loading WebView pages so much faster for my purposes.
Thanks!
You can fetch the http response from the remote url, parse it and replace the remote image urls with local ones via string replace. Then use this html code to display in the webview.
I want to send down a webpage from a server to WebView
Are you talking about 'push' rather than 'pull' mechanism (like as usual with loadUrl())? That's only available in 2.2
(Question: I guess working entirely with local web pages on the device doesn't work in your case, since you need updated versions from the server, right? You only know that the images won't change, correct?)
Sample code for fetching a remote html page - afterwards you'd do the string replacement for your image urls:
/**
* Downloads a remote file and stores it locally
* #param from Remote URL of the file to download
* #param to Local path where to store the file
* #throws Exception Read/write exception
*/
static private void downloadFile(String from, String to) throws Exception {
HttpURLConnection conn = (HttpURLConnection)new URL(from).openConnection();
conn.setConnectTimeout(15000); // timeout 15 secs
conn.setDoInput(true);
conn.connect();
InputStream input = conn.getInputStream();
FileOutputStream fOut = new FileOutputStream(to);
int byteCount = 0;
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = input.read(buffer)) != -1) {
fOut.write(buffer, 0, bytesRead);
byteCount += bytesRead;
}
fOut.flush();
fOut.close();
}
Alternatively you could use
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet("http://www.myurl.com");
HttpResponse res = httpClient.execute(get);
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream input = res.getEntity().getContent();
byte data[] = new byte[14];
input.read(data);
....

Categories

Resources