Upload image file sử dụng Multipart retrofit 2 và php/mysql

1.CÁC BÀI VIẾT TRƯỚC

Trước khi bắt đầu bài viết  các bạn chưa xem các bài viết trước có thể quay lại xem để hiểu hơn:

Ở bài viết trước mình đã hướng dẫn cho các bạn một cách upload file sử dụng retrofit 2 tuy nhiên đó không phải cách theo document.

Hôm nay mình sẽ sử dụng cách chính thức đó là sử dụng Multipart để upload file.

2. Các thư viện sử dụng:

    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
    compile 'com.jakewharton:butterknife:8.4.0'
    apt 'com.jakewharton:butterknife-compiler:8.4.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'

3.Cấu trúc project:

upload-image-use-retrofit2

4.Tạo giao diện upload:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1">

    <Button
        android:text="@string/btnChoose"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnChoose" />

    <TextView
        android:text="@string/title_multipart"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="24sp"
        android:layout_marginBottom="20dp"
        android:id="@+id/textView" />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:srcCompat="@mipmap/ic_launcher"
        android:id="@+id/imgMultipart"
        android:layout_weight="0.87" />

    <Button
        android:text="@string/btnUpload"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnUpload" />

</LinearLayout>

5.Viết trang PHP để xử lý:

<?php
	require_once('dbConnect.php');
	mysqli_set_charset($con,'utf8');
	$response = array();
	if($_SERVER['REQUEST_METHOD']=='POST') { 
		$file_path = "upload/";
		$file_path = $file_path . basename( $_FILES['uploaded_file']['name']);
		if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) {
			$response["message"] = "Success";
		} else{
			$response["message"] = "Failed";
		}
		echo json_encode($result);
	}
?>

6.Viết API 

public interface FileUploadService {
    @Multipart
    @POST("upload.php")
    Call<Message> uploadImage(@Part MultipartBody.Part file);
}

7.Tạo model nhận kết quả

public class Message {
    @SerializedName("message")
    private String message;

  //getter setter
}

8.Tại Activity chính viết các hàm sau:

CheckPermistion

//Check permistion android 6.0
    private void checkPermistion() {
        if (ContextCompat.checkSelfPermission(MultipartUpload.this,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(MultipartUpload.this,
                    Manifest.permission.READ_EXTERNAL_STORAGE)) {

            } else {
                ActivityCompat.requestPermissions(MultipartUpload.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        1);
            }
        }
    }

9.Hàm lấy ảnh trong thư viện: 

Khai báo biến:

String IMAGE_PATH;
private String UPLOAD_URL ="http://dev.androidcoban.com/blog/";

Code gọi Intent nhận dữ liệu:

@OnClick(R.id.btnChoose)
    public void chooseImage(){
        checkPermistion();
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        startActivityForResult(intent, 0);
    }

Nhận dữ liệu intent

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 0 && resultCode == MultipartUpload.this.RESULT_OK) {
            IMAGE_PATH = ReadPathUtil.getPath(MultipartUpload.this, data.getData());
            Uri uri = Uri.fromFile(new File(IMAGE_PATH));
            // Load image
            Glide.with(MultipartUpload.this).load(uri).override(420, 594).centerCrop().into(imageView);
            Toast.makeText(this, IMAGE_PATH, Toast.LENGTH_LONG).show();
        }
    }

10.Lớp util ReadPathUtil.java

public class ReadPathUtil {

    /// get path API >19 KITKAT
    public static String getPath(final Context context, final Uri uri) {

        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] {
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }
}

11.Viết hàm upload dữ liệu:

 @OnClick(R.id.btnUpload)
    public void UploadImage(){
        final ProgressDialog progressDialog;
        progressDialog = new ProgressDialog(MultipartUpload.this);
        progressDialog.setMessage(getString(R.string.string_title_upload_progressbar_));
        progressDialog.show();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(UPLOAD_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        FileUploadService service = retrofit.create(FileUploadService.class);

        File file = new File(IMAGE_PATH);
        // create RequestBody instance from file
        RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);

        // MultipartBody.Part is used to send also the actual file name
        MultipartBody.Part body =
                MultipartBody.Part.createFormData("uploaded_file", file.getName(), requestFile);

        Call<Message> call = service.uploadImage(body);
        call.enqueue(new Callback<Message>() {
            @Override
            public void onResponse(Call<Message> call, Response<Message> response) {
                progressDialog.dismiss();
                Message message = response.body();
                if (message.getMessage().equals("Success")) {
                    Toast.makeText(MultipartUpload.this, R.string.string_upload_success, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MultipartUpload.this, R.string.string_upload_fail, Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<Message> call, Throwable t) {
                progressDialog.dismiss();
                Log.e(TAG, t.toString());
            }
        });
    }

Công đoạn cuối cùng là, tiến hành upload file php lên server. build app.

Chúc các bạn thành công!

Nguyễn Linh

Chia sẻ để cùng tiến bộ...