Android Image Upload

This article is also available in: enEnglisch

Funktionsprinzip vom Image Upload

Dieses Beispiel zeigt, wie man mit Android ein Image an den Server sendet. Dazu wird als Erstes das Foto über einen ImagePicker ausgewählt. Wenn das Bild in der Galerie ausgewählt wurde, zeigt die App den absoluten Pfad vom Foto an. Jetzt leuchtet der Upload-Button grün. Durch Drücken des Upload-Buttons beginnt die App mit dem Upload. Es erscheint ein "Loading Spinner" bis der Upload abgeschlossen wurde oder ein Fehler auftretet. Anschließend wird das Ergebnis vom Server oder eine Fehlermeldung in der TextView angezeigt. Die Datenübertragung wird mittels HTTP-POST an den Server gesendet. Der Code unterstützt auch die Verwendung von HTTPs. Vor der ersten Verwendung sollte man prüfen, ob der Zugriff auf die Daten in den Einstellungen aktiviert ist.

Funktionsprinzip vom PHP Server

Serverseitig läuft ein PHP-Script, der das POST-File entgegen nimmt und auf das Filesystem in den Ordner IMG speichert. Außerdem wird am Server ein Logfile (log.txt) erstellt, der die Uhrzeit und den Dateinamen speichert. Damit die PHP-Anwendung einwandfrei funktioniert, muss das PHP-Script Schreibrechte haben. Außerdem kann es vorkommen, dass Bilddateien, die größer als 2 Megabyte sind, nicht hochgeladen werden können. Um dies zu ändern, muss "upload_max_filesize" & "post_max_size" in der PHP-Konfiguration geändert werden. Der PHP-Script prüft auch, ob es sich bei der gesendeten Datei um ein Foto (JPG, PNG) handelt. Sollte es sich um einen anderen Dateityp handeln, so wird die Datei nicht gespeichert. Für den ersten Test können Sie auch gerne unseren Testserver verwenden. Den Link zum Foto zeigt die App, wenn man diese mit der URL zu unseren Testserver betreibt.
MainActivity.java: Dieser Code befindet sich in der MainActivity.

package com.aeqweb.imagesend;

import ...

public class MainActivity extends Activity {
    Button selectButton, uploadButton;
    TextView view_status;
    ProgressDialog progress;
    String response;
    String realPath;
    String UPLOAD_SERVER = "http://testserver.aeq-web.com/android_send_image/";
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        view_status = (TextView) findViewById(R.id.view_status);
        view_status.setText("Select your Image");
        selectButton = (Button) findViewById(R.id.button);
        selectButton.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
        selectButton.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Open image selector
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*");
                startActivityForResult(intent, 0);
                selectButton.getBackground().setColorFilter(0xffd6d7d7, PorterDuff.Mode.MULTIPLY);
            }
        });

        uploadButton = (Button) findViewById(R.id.button2);
        uploadButton.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Open image selector
                SendImage start_task = new SendImage();
                start_task.execute();
                view_status.setText("Try to upload Image");
                view_status.setTextColor(Color.GRAY);
            }
        });

    }
    @Override
    protected void onActivityResult(int reqCode, int resCode, Intent data) {
        if(resCode == Activity.RESULT_OK && data != null){
            // Check the SDK Version
            if (Build.VERSION.SDK_INT < 11)
                realPath = PathOfImage.PathAPI11(this, data.getData());
            else if (Build.VERSION.SDK_INT < 19)
                realPath = PathOfImage.Path_API18(this, data.getData());
            else
                realPath = PathOfImage.Path_API19(this, data.getData());
            view_status.setText("Image path: " + realPath + "\n\nYou can start the upload now");
            uploadButton.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY);
        }
    }

    public class SendImage extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            progress = new ProgressDialog(MainActivity.this);
            progress.setTitle("Uploading....");
            progress.setMessage("Please wait until the process is finished");
            progress.setCancelable(false); // disable dismiss by tapping outside of the dialog
            progress.show();

        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                response = POST_Data(realPath);
                progress.dismiss();
            } catch (Exception e) {
                response = "Image was not uploaded!";
                progress.dismiss();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            if(response.contains("success"))
            {
                view_status.setTextColor(Color.parseColor("#21c627"));
            }
            view_status.setText(response);
            uploadButton.getBackground().setColorFilter(0xffd6d7d7, PorterDuff.Mode.MULTIPLY);
        }
    }

    public String POST_Data(String filepath) throws Exception {
        HttpURLConnection connection = null;
        DataOutputStream outputStream = null;
        InputStream inputStream = null;
        String boundary =  "*****"+Long.toString(System.currentTimeMillis())+"*****";
        int bytesRead, bytesAvailable, bufferSize;
        byte[] buffer;
        String[] q = filepath.split("/");
        int idx = q.length - 1;
        File file = new File(filepath);
        FileInputStream fileInputStream = new FileInputStream(file);
        URL url = new URL(UPLOAD_SERVER);
        connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("User-Agent", "Android Multipart HTTP Client 1.0");
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary);
        outputStream = new DataOutputStream(connection.getOutputStream());
        outputStream.writeBytes("--" + boundary + "\r\n");
        outputStream.writeBytes("Content-Disposition: form-data; name=\"" + "img_upload" + "\"; filename=\"" + q[idx] +"\"" + "\r\n");
        outputStream.writeBytes("Content-Type: image/jpeg" + "\r\n");
        outputStream.writeBytes("Content-Transfer-Encoding: binary" + "\r\n");
        outputStream.writeBytes("\r\n");
        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, 1048576);
        buffer = new byte[bufferSize];
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        while(bytesRead > 0) {
            outputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, 1048576);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }
        outputStream.writeBytes("\r\n");
        outputStream.writeBytes("--" + boundary + "--" + "\r\n");
        inputStream = connection.getInputStream();
        int status = connection.getResponseCode();
        if (status == HttpURLConnection.HTTP_OK) {
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
            inputStream.close();
            connection.disconnect();
            fileInputStream.close();
            outputStream.flush();
            outputStream.close();
            return response.toString();
        } else {
            throw new Exception("Non ok response returned");
        }
    }
}
PathOfImage.java: Diese Datei ermittelt den richtigen Pfad für das Bild.

package com.aeqweb.imagesend;

import ...

public class PathOfImage {

    @SuppressLint("NewApi")
    public static String Path_API19(Context context, Uri uri) {
        String filePath = "";
        String wholeID = DocumentsContract.getDocumentId(uri);
        String id = wholeID.split(":")[1];
        String[] column = {MediaStore.Images.Media.DATA};
        String sel = MediaStore.Images.Media._ID + "=?";
        Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                column, sel, new String[]{id}, null);
        int columnIndex = cursor.getColumnIndex(column[0]);
        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
        cursor.close();
        return filePath;
    }


    @SuppressLint("NewApi")
    public static String Path_API18(Context context, Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        String result = null;
        CursorLoader cursorLoader = new CursorLoader(
                context,
                contentUri, proj, null, null, null);
        Cursor cursor = cursorLoader.loadInBackground();
        if (cursor != null) {
            int column_index =
                    cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            result = cursor.getString(column_index);
        }
        return result;
    }

    public static String PathAPI11(Context context, Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
        int column_index
                = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }
}
In der Manifest muss der Zugriff auf das Dateisystem und Internet aktiviert werden.

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />