POST Multipart Form Data using Retrofit 2.0 including image

前端 未结 10 1629
名媛妹妹
名媛妹妹 2020-11-22 11:07

I am trying to do a HTTP POST to server using Retrofit 2.0

MediaType MEDIA_TYPE_TEXT = MediaType.parse(\"text/plain\");
MediaType MEDIA_TYPE         


        
相关标签:
10条回答
  • 2020-11-22 11:36

    Update Code for image file uploading in Retrofit2.0

    public interface ApiInterface {
    
        @Multipart
        @POST("user/signup")
        Call<UserModelResponse> updateProfilePhotoProcess(@Part("email") RequestBody email,
                                                          @Part("password") RequestBody password,
                                                          @Part("profile_pic\"; filename=\"pp.png")
                                                                  RequestBody file);
    }
    

    Change MediaType.parse("image/*") to MediaType.parse("image/jpeg")

    RequestBody reqFile = RequestBody.create(MediaType.parse("image/jpeg"),
                                             file);
    RequestBody email = RequestBody.create(MediaType.parse("text/plain"),
                                           "upload_test4@gmail.com");
    RequestBody password = RequestBody.create(MediaType.parse("text/plain"),
                                              "123456789");
    
    Call<UserModelResponse> call = apiService.updateProfilePhotoProcess(email,
                                                                        password,
                                                                        reqFile);
    call.enqueue(new Callback<UserModelResponse>() {
    
        @Override
        public void onResponse(Call<UserModelResponse> call,
                               Response<UserModelResponse> response) {
    
            String
                    TAG =
                    response.body()
                            .toString();
    
            UserModelResponse userModelResponse = response.body();
            UserModel userModel = userModelResponse.getUserModel();
    
            Log.d("MainActivity",
                  "user image = " + userModel.getProfilePic());
    
        }
    
        @Override
        public void onFailure(Call<UserModelResponse> call,
                              Throwable t) {
    
            Toast.makeText(MainActivity.this,
                           "" + TAG,
                           Toast.LENGTH_LONG)
                 .show();
    
        }
    });
    
    0 讨论(0)
  • 2020-11-22 11:37

    Uploading Files using Retrofit is Quite Simple You need to build your api interface as

    public interface Api {
    
        String BASE_URL = "http://192.168.43.124/ImageUploadApi/";
    
    
        @Multipart
        @POST("yourapipath")
        Call<MyResponse> uploadImage(@Part("image\"; filename=\"myfile.jpg\" ") RequestBody file, @Part("desc") RequestBody desc);
    
    }
    

    in the above code image is the key name so if you are using php you will write $_FILES['image']['tmp_name'] to get this. And filename="myfile.jpg" is the name of your file that is being sent with the request.

    Now to upload the file you need a method that will give you the absolute path from the Uri.

    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = {MediaStore.Images.Media.DATA};
        CursorLoader loader = new CursorLoader(this, contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }
    

    Now you can use the below code to upload your file.

     private void uploadFile(Uri fileUri, String desc) {
    
            //creating a file
            File file = new File(getRealPathFromURI(fileUri));
    
            //creating request body for file
            RequestBody requestFile = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
            RequestBody descBody = RequestBody.create(MediaType.parse("text/plain"), desc);
    
            //The gson builder
            Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();
    
    
            //creating retrofit object
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(Api.BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
    
            //creating our api 
            Api api = retrofit.create(Api.class);
    
            //creating a call and calling the upload image method 
            Call<MyResponse> call = api.uploadImage(requestFile, descBody);
    
            //finally performing the call 
            call.enqueue(new Callback<MyResponse>() {
                @Override
                public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
                    if (!response.body().error) {
                        Toast.makeText(getApplicationContext(), "File Uploaded Successfully...", Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
                    }
                }
    
                @Override
                public void onFailure(Call<MyResponse> call, Throwable t) {
                    Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
                }
            });
        }
    

    For more detailed explanation you can visit this Retrofit Upload File Tutorial.

    0 讨论(0)
  • 2020-11-22 11:48

    I am highlighting the solution in both 1.9 and 2.0 since it is useful for some

    In 1.9, I think the better solution is to save the file to disk and use it as Typed file like:

    RetroFit 1.9

    (I don't know about your server-side implementation) have an API interface method similar to this

    @POST("/en/Api/Results/UploadFile")
    void UploadFile(@Part("file") TypedFile file,
                    @Part("folder") String folder,
                    Callback<Response> callback);
    

    And use it like

    TypedFile file = new TypedFile("multipart/form-data",
                                           new File(path));
    

    For RetroFit 2 Use the following method

    RetroFit 2.0 ( This was a workaround for an issue in RetroFit 2 which is fixed now, for the correct method refer jimmy0251's answer)

    API Interface:

    public interface ApiInterface {
    
        @Multipart
        @POST("/api/Accounts/editaccount")
        Call<User> editUser(@Header("Authorization") String authorization,
                            @Part("file\"; filename=\"pp.png\" ") RequestBody file,
                            @Part("FirstName") RequestBody fname,
                            @Part("Id") RequestBody id);
    }
    

    Use it like:

    File file = new File(imageUri.getPath());
    
    RequestBody fbody = RequestBody.create(MediaType.parse("image/*"),
                                           file);
    
    RequestBody name = RequestBody.create(MediaType.parse("text/plain"),
                                          firstNameField.getText()
                                                        .toString());
    
    RequestBody id = RequestBody.create(MediaType.parse("text/plain"),
                                        AZUtils.getUserId(this));
    
    Call<User> call = client.editUser(AZUtils.getToken(this),
                                      fbody,
                                      name,
                                      id);
    
    call.enqueue(new Callback<User>() {
    
        @Override
        public void onResponse(retrofit.Response<User> response,
                               Retrofit retrofit) {
    
            AZUtils.printObject(response.body());
        }
    
        @Override
        public void onFailure(Throwable t) {
    
            t.printStackTrace();
        }
    });
    
    0 讨论(0)
  • 2020-11-22 11:49

    There is a correct way of uploading a file with its name with Retrofit 2, without any hack:

    Define API interface:

    @Multipart
    @POST("uploadAttachment")
    Call<MyResponse> uploadAttachment(@Part MultipartBody.Part filePart); 
                                       // You can add other parameters too
    

    Upload file like this:

    File file = // initialize file here
    
    MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), RequestBody.create(MediaType.parse("image/*"), file));
    
    Call<MyResponse> call = api.uploadAttachment(filePart);
    

    This demonstrates only file uploading, you can also add other parameters in the same method with @Part annotation.

    0 讨论(0)
  • 2020-11-22 11:49

    in kotlin its quite easy, using extensions methods of toMediaType, asRequestBody and toRequestBody here's an example:

    here I am posting a couple of normal fields along with a pdf file and an image file using multipart

    this is API declaration using retrofit:

        @Multipart
        @POST("api/Lesson/AddNewLesson")
        fun createLesson(
            @Part("userId") userId: RequestBody,
            @Part("LessonTitle") lessonTitle: RequestBody,
            @Part pdf: MultipartBody.Part,
            @Part imageFile: MultipartBody.Part
        ): Maybe<BaseResponse<String>>
    

    and here is how to actually call it:

    api.createLesson(
                userId.toRequestBody("text/plain".toMediaType()),
                lessonTitle.toRequestBody("text/plain".toMediaType()),
                startFromRegister.toString().toRequestBody("text/plain".toMediaType()),
                MultipartBody.Part.createFormData(
                    "jpeg",
                    imageFile.name,
                    imageFile.asRequestBody("image/*".toMediaType())
                ),
                MultipartBody.Part.createFormData(
                    "pdf",
                    pdfFile.name,
                    pdfFile.asRequestBody("application/pdf".toMediaType())
                )
    
    0 讨论(0)
  • 2020-11-22 11:49

    Kotlin version with update for deprication of RequestBody.create :

    Retrofit interface

    @Multipart
    @POST("uploadPhoto")
    fun uploadFile(@Part file: MultipartBody.Part): Call<FileResponse>
    

    and to Upload

    fun uploadFile(fileUrl: String){
        val file = File(fileUrl)
        val fileUploadService = RetrofitClientInstance.retrofitInstance.create(FileUploadService::class.java)
        val requestBody = file.asRequestBody(file.extension.toMediaTypeOrNull())
        val filePart = MultipartBody.Part.createFormData(
            "blob",file.name,requestBody
        )
        val call = fileUploadService.uploadFile(filePart)
    
        call.enqueue(object: Callback<FileResponse>{
            override fun onFailure(call: Call<FileResponse>, t: Throwable) {
                Log.d(TAG,"Fckd")
            }
    
            override fun onResponse(call: Call<FileResponse>, response: Response<FileResponse>) {
                Log.d(TAG,"success"+response.toString()+" "+response.body().toString()+"  "+response.body()?.status)
            }
    
        })
    }
    

    Thanks to @jimmy0251

    0 讨论(0)
提交回复
热议问题