+1

Upload single file using retrofit

Xin chào tất cả các bạn, Đây là bài viết viblo đầu tiên của mình, trong bài này mình sẽ giới thiệu cho các bạn cách upload ảnh sử dụng thư viện retrofit. Trong Retrofit 2, Ảnh hoặc bất kì file nào đều được upload dưới dạng Multipart.

Đầu tiên khởi tạo file PHP có tên là "upload.php" và paste đoạn code này vào để tạo server.

<?php

if(isset($_FILES['uploaded_file'])){

	$file_path = "uploads/";

	$file_path = $file_path . basename($_FILES['uploaded_file']['name']);
	if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path) ){
		echo "http://test.toidicode.com/".$file_path;
	} else{
		echo "fail cmnr";
	}
}
?>

Đã 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 và 1 textview hiển thị kết quả trả về. activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/activity_main"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="kekiru.toandoan.com.viblo_uploadfileretrofit.MainActivity">

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

    <TextView
        android:id="@+id/text_response"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_select_image"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:textSize="20sp"/>
</RelativeLayout>

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 mTextResponse;

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

    @Override
    public void onClick(View view) {
        requestPermionAndPickImage();
    }

    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/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"),
            PICK_IMAGE_REQUEST);
    }

    @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.getData() != null) {
            // Khi đã chọn xong ảnh thì chúng ta tiến hành upload thôi
            Uri uri = data.getData();
            uploadFiles(uri);
        }
    }


  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 {
    @Multipart
    @POST("upload.php")
    Call<ResponseBody> uploadFile(@Part MultipartBody.Part file);
}
  • Trong MainActivity chúng ta bắt đầu gọi hàm xử lý.
public void uploadFiles(Uri uri) {
        if (uri == null) return;
        // Hàm call api sẽ mất 1 thời gian nên mình show 1 dialog nhé.
        showProgress();
        File file = new File(getRealPathFromURI(uri));
        // Khởi tạo RequestBody từ file đã được chọn
        RequestBody requestBody = RequestBody.create(
            MediaType.parse(getContentResolver().getType(uri)),
            file);
         // Trong retrofit 2 để upload file ta sử dụng Multipart, khai báo 1 MultipartBody.Part
         // uploaded_file là key mà mình đã định nghĩa trong khi khởi tạo server
        MultipartBody.Part filePart =
            MultipartBody.Part.createFormData("uploaded_file", file.getName(), requestBody);
        Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(new OkHttpClient())
            .build();
        UploadService service = retrofit.create(UploadService.class);
        Call<ResponseBody> call = service.uploadFile(filePart);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response == null || response.body() == null) {
                    mTextResponse.setText(R.string.upload_media_false);
                    return;
                }
                try {
                    String responseUrl = response.body().string();
                    mTextResponse.setText(responseUrl);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                dissmissDialog();
            }

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

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é


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.