Upload multi files using retrofit

Xin chào tất cả các bạn, Ở bài viết đầu tiên mình đã hướng dẫn các bạn sử dụng và upload single file với retrofit Ở bài này mình sẽ hướng dẫn các bạn upload multi files với retrofit

Đầu tiên khởi tạo server.

$data = [];
if(isset($_FILES['uploaded_file']) && is_array($_FILES['uploaded_file'])){
	$file=$_FILES['uploaded_file'];
	$file_path = "uploads/";
	foreach ($file['tmp_name'] as $key => $value) {
		$file_path = $file_path . basename($file['name'][$key]);
		if(move_uploaded_file($file['tmp_name'][$key], $file_path) ){
			$data['message'] = 'success';
			$data['url'][$key] = 'http://test.toidicode.com/'.$file_path;
		} else{
			$data['message'] = 'fail';
		}
	}
	echo json_encode($data);
}
else{
	$data['message'] = 'fail';
	echo json_encode($data);
}

Đã có server vậy chúng ta bắt đầu thôi.

  1. Đầu tiên để có thể upload ảnh sử dụng thư viện retrofit chúng ta cần import thư viện retrofit Thêm compile vào trong file build.gradle
   compile 'com.squareup.retrofit2:retrofit:2.1.0'
   compile 'com.squareup.retrofit2:converter-gson:2.1.0'
  1. Tiếp theo để có thể load ảnh thì chúng ta phải chon được ảnh ở trong máy nên ta yêu cầu quyền READ_EXTERNAL_STORAGE và để có thể upload ảnh thì đương nhiên rồi INTERNET khai báo dòng code sau trong file manifest
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  1. Vậy là đã đủ thư viện và các quyền vậy ta bắt đầu xây dựng giao diện cho app demo, ở đây mình chỉ xây dựng giao diện đơn giản gồm 1 button upload, 1 textview hiển thị danh sách các file sẽ upload và 1 textview hiển thị kết quả trả về. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linear_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp"
    tools:context="lol.toandoan.com.viblo_022017.MainActivity">


    <Button
        android:id="@+id/button_select_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Select Image"/>


    <TextView
        android:id="@+id/text_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="Input"/>

    <TextView
        android:id="@+id/text_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="Result"/>
</LinearLayout>

  • Tiến hành chọn các ảnh để upload MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    // Đây là base url của mình, các bạn thay bằng url của các bạn nhé
    public static final String BASE_URL = "http://test.toidicode.com";
    public final static int PICK_IMAGE_REQUEST = 1;
    public final static int READ_EXTERNAL_REQUEST = 2;
    private ProgressDialog mProgressDialog;
    private TextView mTextResult;
    private TextView mTextInput;
    private LinearLayout mLinearMain;
    private List<Uri> mUris = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button_select_image).setOnClickListener(this);
        mTextResult = (TextView) findViewById(R.id.text_result);
        mTextInput = (TextView) findViewById(R.id.text_input);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button_select_image:
                requestPermionAndPickImage();
                break;
            default:
                break;
        }

    }

    private void requestPermionAndPickImage() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            pickImage();
            return;
        }
        // Các bạn nhớ request permison cho các máy M trở lên nhé, k là crash ngay đấy.
        int result = ContextCompat.checkSelfPermission(this,
                READ_EXTERNAL_STORAGE);
        if (result == PackageManager.PERMISSION_GRANTED) {
            pickImage();
        } else {
            requestPermissions(new String[]{
                    READ_EXTERNAL_STORAGE}, READ_EXTERNAL_REQUEST);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[],
                                           int[] grantResults) {
        if (requestCode != READ_EXTERNAL_REQUEST) return;
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            pickImage();
        } else {
            Toast.makeText(getApplicationContext(), R.string.permission_denied,
                    Toast.LENGTH_LONG).show();
        }
    }

    public void pickImage() {
        // Gọi intent của hệ thống để chọn ảnh nhé.
        Intent intent = new Intent();
        intent.setType("image/*");
        // Thêm dòng này để có thể select nhiều ảnh trong 1 lần nhé các bạn
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select Files to Upload"),
                PICK_IMAGE_REQUEST);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null &&
                data.getClipData() != null) {
            ClipData clipData = data.getClipData();
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < clipData.getItemCount(); i++) {
                ClipData.Item item = clipData.getItemAt(i);
                Uri uri = item.getUri();
                mUris.add(uri);
                builder.append(i + "-")
                        .append(getRealPathFromURI(uri))
                        .append("\n");

            }

            mTextInput.setText(builder.toString());
            // Sau khi get đc data thì ta upload thôi
            uploadFiles();
        }
    }

    private String getRealPathFromURI(Uri contentURI) {
        String result;
        Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
        if (cursor == null) {
            result = contentURI.getPath();
        } else {
            cursor.moveToFirst();
            int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            result = cursor.getString(idx);
            cursor.close();
        }
        return result;
    }
  1. Sau khi chọn được ảnh việc bây giờ của chúng ta là upload ảnh thôi.
  • Tạo class UploadService để define api upload của chúng ta nào
public interface UploadService {
    @POST("/")
    Call<ResponseBody> uploadFileMultilPart(@Body RequestBody files);
}
  • Trong MainActivity chúng ta bắt đầu gọi hàm xử lý.
 public void uploadFiles() {
        if (mUris.isEmpty()) {
            Toast.makeText(this, "Please select some image", Toast.LENGTH_SHORT).show();
            return;
        }
        // Hàm call api sẽ mất 1 thời gian nên mình show 1 dialog nhé.
        showProgress();
        // Trong retrofit 2 để upload file ta sử dụng Multipart, khai báo 1 MultipartBody.Builder
        // uploaded_file là key mà mình đã định nghĩa trong khi khởi tạo server

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(new OkHttpClient())
                .build();

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        for (int i = 0; i < mUris.size(); i++) {
            Uri uri = mUris.get(i);
            File file = new File(getRealPathFromURI(uri));
            // Khởi tạo RequestBody từ những file đã được chọn
            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("image/*"),
                    file);
            // Add thêm request body vào trong builder
            builder.addFormDataPart("uploaded_file", file.getName(), requestBody);
        }

        MultipartBody requestBody = builder.build();
        UploadService service = retrofit.create(UploadService.class);
        Call<ResponseBody> call = service.uploadFileMultilPart(requestBody);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response == null || response.body() == null) {
                    mTextResult.setText(R.string.upload_media_false);
                    return;
                }
                try {
                    String responseUrl = response.body().string();
                    mTextResult.setText(responseUrl);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                dissmissDialog();
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                mTextResult.setText(R.string.upload_media_false);
                dissmissDialog();
            }


        });
    }

    private void dissmissDialog() {
        mProgressDialog.dismiss();
    }

    private void showProgress() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage("Uploading...");
        }
        mProgressDialog.show();
    }

Trên đây là bài hướng dẫn upload file sử dụng retrofit, rất mong được sự đóng góp của các bạn để bài viết được cải thiện hơn, Hãy comment vào bên duới để chúng ta cùng thảo luận các bạn nhé Github https://github.com/DoanVanToan/Viblo_022017