POST Multipart Form Data using Retrofit 2.0 including image

前端 未结 10 1602
名媛妹妹
名媛妹妹 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:50

    Adding to the answer given by @insomniac. You can create a Map to put the parameter for RequestBody including image.

    Code for Interface

    public interface ApiInterface {
    @Multipart
    @POST("/api/Accounts/editaccount")
    Call<User> editUser (@Header("Authorization") String authorization, @PartMap Map<String, RequestBody> map);
    }
    

    Code for Java class

    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));
    
    Map<String, RequestBody> map = new HashMap<>();
    map.put("file\"; filename=\"pp.png\" ", fbody);
    map.put("FirstName", name);
    map.put("Id", id);
    Call<User> call = client.editUser(AZUtils.getToken(this), map);
    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:51

    I used Retrofit 2.0 for my register users, send multipart/form File image and text from register account

    In my RegisterActivity, use an AsyncTask

    //AsyncTask
    private class Register extends AsyncTask<String, Void, String> {
    
        @Override
        protected void onPreExecute() {..}
    
        @Override
        protected String doInBackground(String... params) {
            new com.tequilasoft.mesasderegalos.dbo.Register().register(txtNombres, selectedImagePath, txtEmail, txtPassword);
            responseMensaje = StaticValues.mensaje ;
            mensajeCodigo = StaticValues.mensajeCodigo;
            return String.valueOf(StaticValues.code);
        }
    
        @Override
        protected void onPostExecute(String codeResult) {..}
    

    And in my Register.java class is where use Retrofit with synchronous call

    import android.util.Log;
    import com.tequilasoft.mesasderegalos.interfaces.RegisterService;
    import com.tequilasoft.mesasderegalos.utils.StaticValues;
    import com.tequilasoft.mesasderegalos.utils.Utilities;
    import java.io.File;
    import okhttp3.MediaType;
    import okhttp3.MultipartBody;
    import okhttp3.RequestBody;
    import okhttp3.ResponseBody;
    import retrofit2.Call; 
    import retrofit2.Response;
    /**Created by sam on 2/09/16.*/
    public class Register {
    
    public void register(String nombres, String selectedImagePath, String email, String password){
    
        try {
            // create upload service client
            RegisterService service = ServiceGenerator.createUser(RegisterService.class);
    
            // add another part within the multipart request
            RequestBody requestEmail =
                    RequestBody.create(
                            MediaType.parse("multipart/form-data"), email);
            // add another part within the multipart request
            RequestBody requestPassword =
                    RequestBody.create(
                            MediaType.parse("multipart/form-data"), password);
            // add another part within the multipart request
            RequestBody requestNombres =
                    RequestBody.create(
                            MediaType.parse("multipart/form-data"), nombres);
    
            MultipartBody.Part imagenPerfil = null;
            if(selectedImagePath!=null){
                File file = new File(selectedImagePath);
                Log.i("Register","Nombre del archivo "+file.getName());
                // 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
                imagenPerfil = MultipartBody.Part.createFormData("imagenPerfil", file.getName(), requestFile);
            }
    
            // finally, execute the request
            Call<ResponseBody> call = service.registerUser(imagenPerfil, requestEmail,requestPassword,requestNombres);
            Response<ResponseBody> bodyResponse = call.execute();
            StaticValues.code  = bodyResponse.code();
            StaticValues.mensaje  = bodyResponse.message();
            ResponseBody errorBody = bodyResponse.errorBody();
            StaticValues.mensajeCodigo  = errorBody==null
                    ?null
                    :Utilities.mensajeCodigoDeLaRespuestaJSON(bodyResponse.errorBody().byteStream());
            Log.i("Register","Code "+StaticValues.code);
            Log.i("Register","mensaje "+StaticValues.mensaje);
            Log.i("Register","mensajeCodigo "+StaticValues.mensaje);
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
    }
    

    In the interface of RegisterService

    public interface RegisterService {
    @Multipart
    @POST(StaticValues.REGISTER)
    Call<ResponseBody> registerUser(@Part MultipartBody.Part image,
                                    @Part("email") RequestBody email,
                                    @Part("password") RequestBody password,
                                    @Part("nombre") RequestBody nombre
    );
    }
    

    For the Utilities parse ofr InputStream response

    public class Utilities {
    public static String mensajeCodigoDeLaRespuestaJSON(InputStream inputStream){
        String mensajeCodigo = null;
        try {
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(
                        inputStream, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            inputStream.close();
            mensajeCodigo = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }
        return mensajeCodigo;
    }
    }
    
    0 讨论(0)
  • 2020-11-22 11:51

    Don't use multiple parameters in the function name just go with simple few args convention that will increase the readability of codes, for this you can do like -

    // MultipartBody.Part.createFormData("partName", data)
    Call<SomReponse> methodName(@Part MultiPartBody.Part part);
    // RequestBody.create(MediaType.get("text/plain"), data)
    Call<SomReponse> methodName(@Part(value = "partName") RequestBody part); 
    /* for single use or you can use by Part name with Request body */
    
    // add multiple list of part as abstraction |ease of readability|
    Call<SomReponse> methodName(@Part List<MultiPartBody.Part> parts); 
    Call<SomReponse> methodName(@PartMap Map<String, RequestBody> parts);
    // this way you will save the abstraction of multiple parts.
    

    There can be multiple exceptions that you may encounter while using Retrofit, all of the exceptions documented as code, have a walkthrough to retrofit2/RequestFactory.java. you can able to two functions parseParameterAnnotation and parseMethodAnnotation where you can able to exception thrown, please go through this, it will save your much of time than googling/stackoverflow

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

    So its very simple way to achieve your task. You need to follow below step :-

    1. First step

    public interface APIService {  
        @Multipart
        @POST("upload")
        Call<ResponseBody> upload(
            @Part("item") RequestBody description,
            @Part("imageNumber") RequestBody description,
            @Part MultipartBody.Part imageFile
        );
    }
    

    You need to make the entire call as @Multipart request. item and image number is just string body which is wrapped in RequestBody. We use the MultipartBody.Part class that allows us to send the actual file name besides the binary file data with the request

    2. Second step

      File file = (File) params[0];
      RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
    
      MultipartBody.Part body =MultipartBody.Part.createFormData("Image", file.getName(), requestBody);
    
      RequestBody ItemId = RequestBody.create(okhttp3.MultipartBody.FORM, "22");
      RequestBody ImageNumber = RequestBody.create(okhttp3.MultipartBody.FORM,"1");
      final Call<UploadImageResponse> request = apiService.uploadItemImage(body, ItemId,ImageNumber);
    

    Now you have image path and you need to convert into file.Now convert file into RequestBody using method RequestBody.create(MediaType.parse("multipart/form-data"), file). Now you need to convert your RequestBody requestFile into MultipartBody.Part using method MultipartBody.Part.createFormData("Image", file.getName(), requestBody); .

    ImageNumber and ItemId is my another data which I need to send to server so I am also make both thing into RequestBody.

    For more info

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