In my previous tutorial How to upload a file to server in android i am explaining how to upload an image to server. But this is a time taking process and the code is also very complex. As we all know that images can be converted into base 64 encoded string in java.So why can’t we upload image as a string.This can increase the speed of image upload with simple data upload code.
In this tutorial we will learn how to upload an image to server as a base64 encoded string in android .The mechanism behind this. is we will convert our bitmap image to base64 encoded string and decode image in php and save the image to our folder in server. The advantage of uploading image as base64 is we can reduce the time of uploading and complexity of code.
Recomended to use android Volley library for doing this task which is most flexible way of file upload in android.
Steps
- Create new project in android studio
- Implement the layout for the screen
- Java code for uploading image as base64 encoded string
- php code for decoding image
Create New project in android studio
Refer Android beginners app development guide if you are beginner or if you don’t know how to create project in android studio.
Implement the layout for the screen
For uploading an image there has to be an action from the android end. So we will have a button inside the layout which onclick will open the gallery and pick the image for uploading.
<Button
android:id="@+id/btn_upload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload" />
Implement the java code for uploading image as base64 encoded string
Now simply add the following code to your activity. This will contain reference of the above button. While clicking on button it will open Gallery , and after selecting the image. It will come back to onActivityResult method of activity and start code for uploading file to server.
Here is the full code for your activity
package com.uploadfile; import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Base64; import android.view.View; import android.widget.Button; import android.widget.Toast; import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; public class MainActivity extends AppCompatActivity { ProgressDialog pDialog; String image; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pDialog = new ProgressDialog(this); Button btn_upload = (Button) findViewById(R.id.btn_upload); btn_upload.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, 0); } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (data != null && requestCode == 0) { if (resultCode == RESULT_OK) { Uri targetUri = data.getData(); Bitmap bitmap; try { bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri)); Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 500, 500, false); image = ConvertBitmapToString(resizedBitmap); Upload(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //method to convert the selected image to base64 encoded string public static String ConvertBitmapToString(Bitmap bitmap){ String encodedImage = ""; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); try { encodedImage= URLEncoder.encode(Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return encodedImage; } private void Upload() { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { new UploadFile().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "your api link"); } else { new UploadFile().execute("your api link"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private class UploadFile extends AsyncTask<String, Void, Void> { private String Content; private String Error = null; String data = ""; private BufferedReader reader; protected void onPreExecute() { pDialog.show(); try { data += "&" + URLEncoder.encode("image", "UTF-8") + "=" + "data:image/png;base64," + image; } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } protected Void doInBackground(String... urls) { HttpURLConnection connection = null; try { URL url = new URL(urls[0]); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); con.setUseCaches(false); con.setDoInput(true); con.setDoOutput(true); con.setRequestProperty("Content-Length", "" + data.getBytes().length); con.setRequestProperty("Connection", "Keep-Alive"); con.setDoOutput(true); OutputStream os = con.getOutputStream(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); //make request writer.write(data); writer.flush(); writer.close(); reader = new BufferedReader(new InputStreamReader(con.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); } Content = sb.toString(); } catch (Exception ex) { Error = ex.getMessage(); } return null; } protected void onPostExecute(Void unused) { // NOTE: You can call UI Element here. pDialog.dismiss(); try { if (Content != null) { JSONObject jsonResponse = new JSONObject(Content); String status = jsonResponse.getString("status"); if ("200".equals(status)) { Toast.makeText(getApplicationContext(), "File uploaded successfully", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "Something is wrong ! Please try again.", Toast.LENGTH_SHORT).show(); } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
Implement the php code for decoding image at the server level
We provided an api link in the above java code which will be the link to one file in our server. This will be a php file which will contain the code for decoding the base 64 image which is sent by the android. And after decoding it you can move it to any of your folder in the server with reference in your database. Following is the code for decoding and moving it into folder inside server.
<?php require_once('conn/config.php');//use path and name of your connection file $base64_string=$_POST['image']; $image_name = uniqid().".png"; if(validateString($base64_string)) { $data = explode(',', $base64_string); $ifp = fopen($_SERVER['DOCUMENT_ROOT'] ."/images/".$image_name, "wb");// use your folder path fwrite($ifp, base64_decode($data[1])); fclose($ifp); //inserting the picture name to your table , here i am just inserting pic name, you can insert //other details also $query = "INSERT INTO your_table(pic) VALUES (?)"; $stmt = $con->prepare($query); $stmt->bind_param("s",$image_name); $stmt->execute(); $id=$stmt->insert_id; if($stmt->affected_rows==1){ $final_arr=array(); $final_arr["status"] = "200"; $final_arr["msg"] = "successful"; print_r(json_encode($final_arr)); }else{ $final_arr=array(); $final_arr["status"] = "401"; $final_arr["msg"] = "Not successful"; print_r(json_encode($final_arr)); } } else { $final_arr=array(); $final_arr["status"] = "501"; $final_arr["msg"] = "Unsccessfull"; print_r(json_encode($final_arr)); } //function to validate base64 string function validateString($string) { $data = explode(',', $string); if(count($data) >= 2) { $format = explode('/', $data[0]); if($format[0] == 'data:image') { return true; } } return false; } ?>
The received base64 encoded string fails on validation. It seems count($data) <2 . But If I omit the explode() function. Then it returns a jpg image that I cannot open. Says it is corrupted. But Its size is not zero.
Are you using the tutorial code to upload? or you are using just base64 conversion code?
Thanks so much