In my application I am attempting to upload a photo to my server via a LAN connection. I started with this tutorial: Sending Image to Server, but found out that it used deprecated methods - HttpParams & HttpClient to be specific. Upon searching, I found HttpUrlConnection, and am trying to fix the app to upload a photo.
Here is my Android Code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final int RESULT_LOAD_IMAGE = 1;
private static final String SERVER_ADDRESS = "http://my__LAN_IP_address/SavePicture.php";
HttpURLConnection urlConnection = null;
ImageView imageToUpload, downloadedImage;
Button bUploadImage, bDownloadImage;
EditText uploadImageName, downLoadImageName;
InputStream is;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageToUpload = (ImageView) findViewById(R.id.imageToUpload);
downloadedImage = (ImageView) findViewById(R.id.downloadedImage);
bUploadImage = (Button) findViewById(R.id.bUploadImage);
bDownloadImage = (Button) findViewById(R.id.bDownloadImage);
uploadImageName = (EditText) findViewById(R.id.etUploadImage);
downLoadImageName = (EditText) findViewById(R.id.etDownloadName);
imageToUpload.setOnClickListener(this);
bUploadImage.setOnClickListener(this);
bDownloadImage.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.imageToUpload:
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, RESULT_LOAD_IMAGE);
break;
case R.id.bUploadImage:
Bitmap image = ((BitmapDrawable) imageToUpload.getDrawable()).getBitmap();
new UploadImage(image, uploadImageName.getText().toString()).execute();
break;
case R.id.bDownloadImage:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && data != null){
Uri selectedImage = data.getData();
imageToUpload.setImageURI(selectedImage);
}
}
private class UploadImage extends AsyncTask<Void, Void, Void>{
Bitmap image;
String name;
public UploadImage(Bitmap image, String name){
this.image = image;
this.name = name;
}
@Override
protected Void doInBackground(Void... params) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
String encodedImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
ContentValues dataToSend = new ContentValues();
dataToSend.put("image", encodedImage);
dataToSend.put("name", name);
try{
URL url = new URL(SERVER_ADDRESS);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(3000);
connection.setConnectTimeout(3000);
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
os = connection.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(String.valueOf(dataToSend));
writer.flush();
writer.close();
os.close();
connection.connect();
is = connection.getInputStream();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
Toast.makeText(getApplicationContext(), "Image Uploaded", Toast.LENGTH_SHORT).show();
}
}
}
And here is my php code:
<?php
$name = isset($_POST["name"]) ? $_POST["name"] : '';
$image = isset($_POST["image"]) ? $_POST["image"] : '';
$decodedImage = base64_decode("$image");
file_put_contents("pictures/" + $name + ".JPG", $decodedImage);
?>
Upon running the app and selecting a photo, nothing errors out and it seems to work, but looking server side, there are no photos getting uploaded. Any help would be greatly appreciated.
Use this
//File path
String filepath = ""
@Override
protected String doInBackground(Void... params) {
String responseString = null;
HttpURLConnection conn = null;
DataOutputStream dos = null;
DataInputStream inStream = null;
String lineEnd = "
";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead;
long sentData = 0;
//URL
String urlString = ""
try {
UUID uniqueKey = UUID.randomUUID();
String fname = uniqueKey.toString();
FileInputStream fileInputStream = new FileInputStream(new File(filePath));
int length = fileInputStream.available();
URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
conn.setChunkedStreamingMode(1024);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\""+ (new File(filePath)).getName()+"\"" + lineEnd);
dos.writeBytes(lineEnd);
int maxBufferSize = 1024;
int bufferSize = Math.min(length, maxBufferSize);
byte[ ] buffer = new byte[bufferSize];
bytesRead = 0;
int latestPercentDone;
int percentDone = -1;
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bytesRead);
sentData += bytesRead;
latestPercentDone = (int) ((sentData / (float) length) * 100);
if (percentDone != latestPercentDone) {
percentDone = latestPercentDone;
publishProgress(percentDone);
}
int bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable,maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
} catch (IOException ioe) {
}
try {
statusCode = conn.getResponseCode();
if (statusCode == 200) {
responseString = "File Uploaded";
} else {
responseString = "Error occurred! Http Status Code: "
+ statusCode;
}
} catch (IOException ioex) {
responseString = ioex.getMessage();
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
System.out.println(result)
}
Also, try writing the file somewhere before uploading. It will be useful if the upload fails and you want to retry later.
I had a similar problem yesterday. I hat to send both images and text. After trying different ways i ended in using okhttp3: https://github.com/square/okhttp. In my opinion it was the simplest way.
In Android studio first you have to add okhttp to your project. Add it under dependencies in your build.gradle file:
dependencies {
compile 'com.squareup.okhttp3:okhttp:3.2.0
}
My java file in the android project looks similar to the following. It is part of a fragment class. So if you'll use it in an activity you might change getActivity() with this to get the context. I stored the paths to the files i want to send in an ArrayList (variable imageList). The function backgroundThreadAlert is just needed for the response. If you don't need to know wether the upload succeeded or not you may ignore this function.
public class UploadClient extends AsyncTask<String, String, JSONObject> {
private ProgressDialog progressBar;
String status = "";
String formname = "mytext";
@Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = new ProgressDialog(getActivity());
progressBar.setMessage("Send files. Please wait...");
progressBar.setIndeterminate(false);
progressBar.setCancelable(false);
progressBar.show();
}
@Override
protected JSONObject doInBackground(String... params) {
try {
int picindex = 0;
String url = "https://<urltouploadphp>/upload.php";
MultipartBody.Builder buildernew = new MultipartBody.Builder();
buildernew.setType(MultipartBody.FORM);
buildernew.addFormDataPart("formname", formname);
for(int j = 0; j < imageList.size(); j++) { // imageList is a ArrayList<String> of local paths of the images i want to upload
String imagepath = imageList.get(j);
File imgfile = new File(imagepath);
if(imgfile.exists()) {
buildernew.addFormDataPart("file" + picindex, imagepath, RequestBody.create(MediaType.parse("image/*"), imgfile));
picindex++;
}
}
MultipartBody requestBody = buildernew.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException throwable) {
throwable.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
try {
String jsonData = response.body().string();
JSONObject Jobject = new JSONObject(jsonData);
status = Jobject.getString("status");
} catch (JSONException e) {
// Error in json
}
backgroundThreadAlert(getActivity());
}
});
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(JSONObject json) {
if (progressBar.isShowing()) {
progressBar.dismiss();
}
}
// Looper function to call from background thread "onResponse" - in this case a AlertDialog
public void backgroundThreadAlert(final Context context) {
if (context != null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
AlertDialog.Builder warnSend = new AlertDialog.Builder(getActivity());
@Override
public void run() {
if (status.equals("FAILED")) {
warnSend.setTitle("Upload failed");
warnSend.setMessage("upload to server failed");
} else if (status.equals("SUCCESS")) {
warnSend.setTitle("Upload completed");
warnSend.setMessage("upload completed, images sent.");
} else {
// error - no connection to server ?
}
warnSend.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
warnSend.show();
}
});
}
}
}
Call the task with this:
new UploadClient().execute();
My upload.php file on the server looks similar to this one:
<?php
$name = $_POST['formname'];
for($i = 0; $i < count($_FILES); $i++) {
$fileName = $_FILES['file'.$i]['name'];
$fileType = $_FILES['file'.$i]['type'];
$rootName = explode(".", $fileName)[0];
$extension = explode(".", $fileName)[1];
$newName = $rootName.".".$extension;
$moved = move_uploaded_file($_FILES["file".$i]["tmp_name"], $newName );
if ($moved) $path = $newName;
}
// JSON-Response
$time = time();
if ($moved) {
$arrayToSend = array('status'=>'SUCCESS','time'=>$time, 'name'=>$name, 'countPics'=>count($_FILES));
} else {
$arrayToSend = array('status'=>'FAILED','time'=>$time);
}
header('Content-Type:application/json');
echo json_encode($arrayToSend);
?>
Hope, it helps.