I have a MariaDB database where I insert data via a php file by making a post request.
I now want to retrieve all the database content via PHP in the form of CSV.
I've found a PHP file that downloads the database content as csv and it works.
This is the code I had at first:
String url = allConstants.BASE_URL + "exportData.php";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
The above code works but it opens up momentarily the browser and then the file is downloaded. I don't want that to happen. I want the file to be downloaded in the background without opening anything.
I have also tried using Async task and making a post request.
#Override
protected String doInBackground(String... params)
{
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(allConstants.BASE_URL + "exportData.php")
.method("GET", null)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
try
{
response = client.newCall(request).execute();
} catch (IOException e)
{
e.printStackTrace();
}
Log.i(TAG, "reresponse: " + response);
return null;
}
The above code seems to execute the PHP file, but no csv file is downloaded on device.
What modifications are needed for the above code in order to work?
Do I need to save the database content to a variable first and then save it to the user's device? If that's the case, I don't see why, since the PHP file does exactly that.
Related
I've build a simple REST API in PHP which fires a query to my MySQL database (fully utf-8 encoded) and returns the result as a JSON array. In PHP I also set the charset to UTF-8: mysqli_set_charset($con, "UTF8");.
So when I call my Service like http://<host>/getData.php in my web browser I get something like this:
[{"id":"6","name":"föö","content":"bär"}]
which is totally correct.
Additionally I'm calling my REST Service out of my Android App using OkHttp3. But this always gives me the following output:
[{"id":"6","name":"föö","content":"bär"}]
Obviously there is something wrong with the charset or something like that.
Here is my JAVA code:
OkHttpClient client = new OkHttpClient();
HttpUrl.Builder urlBuilder = HttpUrl.parse(config.getServerRoot() + php).newBuilder();
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.url(url)
.build();
// Get a handler that can be used to post to the main thread
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
// Check for failure
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
// Read data on the worker thread
final String result = response.body().string();
// result = [{"id":"6","name":"föö","content":"bär"}]
}
});
Can you tell me what I'm doing wrong?
Ok, i got it! Renan Arceno reminded me, that my Rest Service is giving me HTML entities. So instead of using Html.fromHtml(result) in Java - which obviously works as well - I removed the PHP function htmlentities() which converts my characters to HTML entities.
Now it works. Thanks to you!
I am retrieving JSON objects from a PHP file to my Android app. One of the objects attributes is an image file name. All images are hosted on a web folder.
At this moment, the object attribute is the image file name, but I need the complete URL to the file to be able to display the image on the app.
What should I do to obtain a better performance:
Add the URL string to the file name at the PHP file prior to execute the JSONencode function?
Add the URL string to the file name at the app code after receiving the JSON array from the web server?
This is the piece of code I am using to retrieve the JSON array:
protected Void doInBackground(Void... params) {
// Create an array
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given URL address
jsonobject = JSONfunctions
.getJSONfromURL("http://.../android_ofertaslist_todas.php");
try {
// Locate the array name in JSON
jsonarray = jsonobject.getJSONArray("Categorias");
for (int i = 0; i < jsonarray.length(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
jsonobject = jsonarray.getJSONObject(i);
// Retrive JSON Objects
map.put("valoracionEmpresa", jsonobject.getString("valoracionEmpresa"));
map.put("nombreEmpresa", jsonobject.getString("nombreEmpresa"));
map.put("direccionEmpresa", jsonobject.getString("direccionEmpresa"));
map.put("strImagen", jsonobject.getString("strImagen"));//<--- THIS IS THE IMAGE FILE NAME
// Set the JSON Objects into the array
arraylist.add(map);
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
both ways will result same performance:
Add the URL string to the file name at the PHP file prior to execute the JSONencode function?
Add the URL string to the file name at the app code after receiving the JSON array from the web server?
better way is add url string at server side and retrieve absolute path of image in json, so that in future you can change the location of your images and url on server without doing any change at your mobile app code.
I have a remote database with MySQL, and I am storing photos of the users of my app on the database as a row of the database with LONGTEXT type.
I transform the photos to a string with Base64.
I connect to my remote database with JSON and PHP, because this, I have to use Base64, because as I know, JSON and PHP need to send strings on the parameters, and with Base64 I can transform the photo into a string.
It works ok, but it's very slow. When I am loading a photo of 100 KB, it takes a lot of time, but when I am loading a photo of 5 KB it takes only two or three seconds.
A friend told me to use BLOB instead of Base64, but how do I use BLOB with JSON and a PHP connection to the database? Also, I need to store the images on a row of the table USER. This is because the users don't have privileges to upload files into the remote server, but they can upload photos by uploading them as a string in a row of the table USER.
thanks
EDIT:
this is the code where it takes a looot time waiting (it waits in the line: while ((line = reader.readLine()) != null) { , it is waiting on reader.readLine() )
this code gets one user from the remote database, it takes a loooooot of time to show the user on my app
public Friend RetrieveOneUser(String email)
{
Friend friend=null;
String result = "";
//the parameter data to send
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email",email));
//http post
InputStream is=null;
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(this.BaseURL + this.GetOneUser_URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection "+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
//parse json data
try{
JSONArray jArray = new JSONArray(result);
for(int i=0;i<jArray.length();i++)
{
JSONObject json_data = jArray.getJSONObject(i);
friend=new Friend(json_data.getString("email"),json_data.getString("password"), json_data.getString("fullName"), json_data.getString("mobilePhone"), json_data.getString("mobileOperatingSystem"),"",json_data.getString("photo"));
}
}
catch(JSONException e){
Log.e("log_tag", "Error parsing data "+e.toString());
}
return friend;
}
Segment the request into two parts:
First downloads the JSON with everything except the image, return a reference to the image as a URL instead
Second download the image as a binary chunk, potentially asynchronously depending on the app
I'm assuming you have something like http://example.com/userinfo/xxx as an endpoint that returns the JSON? Add an endpoint like http://example.com/userinfo_image/xxx to return just the image, then you can return it as a binary chunk instead of Base64 encoding it in the JSON.
It means you make two HTTP requests instead of one, but depending on the app you might be able to do the image load asynchronously, and if so you normally get a big gain in perceived application response time from the users perspective.
For info about lazy loading images in the background see the post on the Android Developers blog for a sample:
http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html
If you can't lazy load the image consider doing parallel requests for both the image and the JSON at the same time. With the binary version of the image taking a lot less network bandwidth, and a lot less processing once you get the data onto the handset, it should still seem a lot more speedy.
Why not dump your image as a file on the server and return the url of the written file in your json? This is really how you should do what you want to do since http is the protocol you should use for transfering images over the web.
Code similar to this should do what you want on the server
//code to get your row from database
//Code that writes it to a file.
$Data = $row['myblobfield'];
$fp = fopen('myimgname.jpg', 'w');
fwrite($fp, $Data);
fclose($fp);
This will write your blob or longtext fields as a file on your server which you can then download from your mobile app. You can then delete this temp files after an interval.
Hope this is useful
To answer your question:
No, JSON doesn't support binary data, you must escape it in some way before sending it. Storing it as BLOB in MySQL is not going to fix the major infrastructure issues you have.
From what I understand you have an Android device that is uploading a picture to a PHP server, this PHP server is encoding the picture to Base64, putting that into a JSON string and then posting it to a remote(how remote is remote? same data center? across the country? across the world? in outer space orbiting the moon?) MySQL server through an HTTP interface of some sort, that MySQL server is storing the Base64 image as LONGTEXT. To get the image back, the Android Client sends a request to PHP, PHP sends a request to the remote MySQL server, PHP then has to Base64 decode the image and send it down.
This is horribly inefficient, you are going to suffer latency every step of the way.
Edit: okay it looks like this is a client side issue and not a server side issue...
If that's the case then I'd suggest checking the posts # Uploading images to a PHP server from Android as they should have some more efficient examples.
Is the slowness coming from json/base64 encoding 100K of data, or from the database hit? Its probably from the encoding, and putting the files in the file system (as everyone in the comments is crying), on a small scale, is not going to make a bit of difference.
Do some measurements on the different parts of the operation, and try to pinpoint why its slow. I don't know how else you'd get an image blob into a json encoded string without base64, i suppose you could try and escape everything, which might be just as slow, and hope the parser doesn't choke on it.
Are you using the json_encode function in php, or manually building the string? Try building it manually. Are you base64 encoding raw data from the database, or is it encoded before its stored, you should encode it before its stored to save time when outputting.
I'm going nuts! Maybe someone can help me?!
I have an sqlite-database on a running server, which I receive due to an php-script. (To make it clear: I'm calling an php-script which gives me the the database as a response). With the response I'm now trying to "parse" it to an regular *.db file which I later on use for my app.
the app works fine, while placing the *.db into the assets folder. But I need to get the updated database everytime when calling the app. Therefore I need to receive it somehow from the server.
Just for notice: I don't know why they use a php-script for that, but it works perfectly with the iOS-Version of the app. So I am 100% sure that the script does work.
Got any hints or a solution to that?
Thanks!
EDIT: here is what I'm trying to do.
private void copyDatabase() {
InputStream myInputDB = null;
OutputStream myOutputDB = null;
HttpResponse response = null;
// Path to the just created empty db
String dbFilePath = DB_PATH + KeyConstants.DB_NAME;
// Creating HTTP client
HttpClient httpClient = new DefaultHttpClient();
// Creating HTTP Post
HttpPost httpPost = new HttpPost(
"http://USERNAME:PASSWORD#ADRESS/u/db.php");
try {
response = httpClient.execute(httpPost);
//Open your local db as the input stream
myInputDB = response.getEntity().getContent();
//Open the empty db as the output stream
myOutputDB = new FileOutputStream(dbFilePath);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInputDB.read(buffer)) > 0){
myOutputDB.write(buffer, 0, length);
}
//Close the streams
myOutputDB.flush();
myOutputDB.close();
myInputDB.close();
} catch (IOException ioEXC) {
throw new Error("Problem copying database from resource file.");
}
What do You have the problem with? With the Android app or with the PHP script?
I don't understand why there is a whole DB file request-response and not just the data (and better in some lazy reading), but that's not matter of Your case.
If You need to "download" all the DB at every run You should call and implement some method to do so - in the very first Activity call this method within onCreate() method. You can create a simple method within this Activity or in better approach create a simple class for this that will be instanciated and its method called within the first activity's onCreate().
But maybe I just don't understand You question...
EDIT: try reading through this problem: Can I download an SQLite db on /sdcard and access it from my Android app?
I have a remote database with MySQL, and I am storing photos of the users of my app on the database as a row of the database with LONGTEXT type.
I transform the photos to a string with Base64.
I connect to my remote database with JSON and PHP, because this, I have to use Base64, because as I know, JSON and PHP need to send strings on the parameters, and with Base64 I can transform the photo into a string.
It works ok, but it's very slow. When I am loading a photo of 100 KB, it takes a lot of time, but when I am loading a photo of 5 KB it takes only two or three seconds.
A friend told me to use BLOB instead of Base64, but how do I use BLOB with JSON and a PHP connection to the database? Also, I need to store the images on a row of the table USER. This is because the users don't have privileges to upload files into the remote server, but they can upload photos by uploading them as a string in a row of the table USER.
thanks
EDIT:
this is the code where it takes a looot time waiting (it waits in the line: while ((line = reader.readLine()) != null) { , it is waiting on reader.readLine() )
this code gets one user from the remote database, it takes a loooooot of time to show the user on my app
public Friend RetrieveOneUser(String email)
{
Friend friend=null;
String result = "";
//the parameter data to send
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("email",email));
//http post
InputStream is=null;
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(this.BaseURL + this.GetOneUser_URL);
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
}catch(Exception e){
Log.e("log_tag", "Error in http connection "+e.toString());
}
//convert response to string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
result=sb.toString();
}catch(Exception e){
Log.e("log_tag", "Error converting result "+e.toString());
}
//parse json data
try{
JSONArray jArray = new JSONArray(result);
for(int i=0;i<jArray.length();i++)
{
JSONObject json_data = jArray.getJSONObject(i);
friend=new Friend(json_data.getString("email"),json_data.getString("password"), json_data.getString("fullName"), json_data.getString("mobilePhone"), json_data.getString("mobileOperatingSystem"),"",json_data.getString("photo"));
}
}
catch(JSONException e){
Log.e("log_tag", "Error parsing data "+e.toString());
}
return friend;
}
Segment the request into two parts:
First downloads the JSON with everything except the image, return a reference to the image as a URL instead
Second download the image as a binary chunk, potentially asynchronously depending on the app
I'm assuming you have something like http://example.com/userinfo/xxx as an endpoint that returns the JSON? Add an endpoint like http://example.com/userinfo_image/xxx to return just the image, then you can return it as a binary chunk instead of Base64 encoding it in the JSON.
It means you make two HTTP requests instead of one, but depending on the app you might be able to do the image load asynchronously, and if so you normally get a big gain in perceived application response time from the users perspective.
For info about lazy loading images in the background see the post on the Android Developers blog for a sample:
http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html
If you can't lazy load the image consider doing parallel requests for both the image and the JSON at the same time. With the binary version of the image taking a lot less network bandwidth, and a lot less processing once you get the data onto the handset, it should still seem a lot more speedy.
Why not dump your image as a file on the server and return the url of the written file in your json? This is really how you should do what you want to do since http is the protocol you should use for transfering images over the web.
Code similar to this should do what you want on the server
//code to get your row from database
//Code that writes it to a file.
$Data = $row['myblobfield'];
$fp = fopen('myimgname.jpg', 'w');
fwrite($fp, $Data);
fclose($fp);
This will write your blob or longtext fields as a file on your server which you can then download from your mobile app. You can then delete this temp files after an interval.
Hope this is useful
To answer your question:
No, JSON doesn't support binary data, you must escape it in some way before sending it. Storing it as BLOB in MySQL is not going to fix the major infrastructure issues you have.
From what I understand you have an Android device that is uploading a picture to a PHP server, this PHP server is encoding the picture to Base64, putting that into a JSON string and then posting it to a remote(how remote is remote? same data center? across the country? across the world? in outer space orbiting the moon?) MySQL server through an HTTP interface of some sort, that MySQL server is storing the Base64 image as LONGTEXT. To get the image back, the Android Client sends a request to PHP, PHP sends a request to the remote MySQL server, PHP then has to Base64 decode the image and send it down.
This is horribly inefficient, you are going to suffer latency every step of the way.
Edit: okay it looks like this is a client side issue and not a server side issue...
If that's the case then I'd suggest checking the posts # Uploading images to a PHP server from Android as they should have some more efficient examples.
Is the slowness coming from json/base64 encoding 100K of data, or from the database hit? Its probably from the encoding, and putting the files in the file system (as everyone in the comments is crying), on a small scale, is not going to make a bit of difference.
Do some measurements on the different parts of the operation, and try to pinpoint why its slow. I don't know how else you'd get an image blob into a json encoded string without base64, i suppose you could try and escape everything, which might be just as slow, and hope the parser doesn't choke on it.
Are you using the json_encode function in php, or manually building the string? Try building it manually. Are you base64 encoding raw data from the database, or is it encoded before its stored, you should encode it before its stored to save time when outputting.