recyclerview peticiones implementar example ejemplo android retrofit androidhttpclient retrofit2

android - peticiones - retrofit implementation java



POST Datos de formulario multiparte utilizando Retrofit 2.0, incluida la imagen (7)

Estoy tratando de hacer una POST HTTP al servidor usando Retrofit 2.0

MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/plain"); MediaType MEDIA_TYPE_IMAGE = MediaType.parse("image/*"); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); imageBitmap.compress(Bitmap.CompressFormat.JPEG,90,byteArrayOutputStream); profilePictureByte = byteArrayOutputStream.toByteArray(); Call<APIResults> call = ServiceAPI.updateProfile( RequestBody.create(MEDIA_TYPE_TEXT, emailString), RequestBody.create(MEDIA_TYPE_IMAGE, profilePictureByte)); call.enqueue();

El servidor devuelve un error diciendo que el archivo no es válido.

Esto es extraño porque he intentado cargar el mismo archivo con el mismo formato en iOS (usando otra biblioteca), pero se carga con éxito.

Me pregunto cuál es la forma correcta de cargar una imagen usando Retrofit 2.0 .

¿Debo guardarlo en el disco antes de cargarlo?

PD: He utilizado la actualización para otra solicitud de varias partes que no incluye imagen y se completaron con éxito. El problema es cuando intento incluir un byte en el cuerpo.


Código de actualización para la carga de archivos de imagen en 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); }

Cambie MediaType.parse("image/*") a MediaType.parse("image/jpeg")

RequestBody reqFile = RequestBody.create(MediaType.parse("image/jpeg"), file); RequestBody email = RequestBody.create(MediaType.parse("text/plain"), "[email protected]"); 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(); } });


Cargar archivos usando Retrofit es bastante simple. Necesita construir su interfaz api como

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); }

en la imagen de código anterior está el nombre de la clave, por lo que si está utilizando php, escribirá $ _FILES [''image''] [''tmp_name''] para obtener esto. Y filename = "myfile.jpg" es el nombre del archivo que se envía con la solicitud.

Ahora para cargar el archivo necesita un método que le dará la ruta absoluta desde el 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; }

Ahora puede usar el siguiente código para cargar su archivo.

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(); } }); }

Para obtener una explicación más detallada, puede visitar este Tutorial de actualización de archivos de carga .


Entonces, es una forma muy simple de lograr su tarea. Debe seguir el siguiente paso: -

1. Primer paso

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

@Multipart request realizar la llamada completa como @Multipart request . item e image number es solo el cuerpo de la cadena que está envuelto en RequestBody . Utilizamos la MultipartBody.Part class que nos permite enviar el nombre del archivo real además de los datos del archivo binario con la solicitud

2. Segundo paso

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

Ahora tiene la image path y necesita convertirla en file . Ahora convierta el file en RequestBody usando el método RequestBody.create(MediaType.parse("multipart/form-data"), file) . Ahora necesita convertir su RequestBody requestFile en MultipartBody.Part usando el método MultipartBody.Part.createFormData("Image", file.getName(), requestBody); .

ImageNumber y ItemId son mis otros datos que necesito enviar al servidor, por lo que también hago ambas cosas en RequestBody .

Para más información


Estoy destacando la solución en 1.9 y 2.0 ya que es útil para algunos

En 1.9 , creo que la mejor solución es guardar el archivo en el disco y usarlo como archivo Mecanografiado como:

RetroFit 1.9

(No sé acerca de su implementación del lado del servidor) tiene un método de interfaz API similar a este

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

Y úsalo como

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

Para RetroFit 2, use el siguiente método

RetroFit 2.0 (Esta fue una solución para un issue en RetroFit 2 que se solucionó ahora; para el método correcto, consulte la respuesta de jimmy0251 )

Interfaz API:

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); }

Úselo como:

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(); } });


Hay una forma correcta de cargar un archivo con su nombre con Retrofit 2 , sin ningún truco :

Definir interfaz API:

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

Sube un archivo como este:

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

Esto demuestra solo la carga de archivos, también puede agregar otros parámetros en el mismo método con la anotación @Part .


Utilicé Retrofit 2.0 para mis usuarios registrados, envié una imagen de archivo multipart / form y texto desde la cuenta de registro

En mi RegisterActivity, use una 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) {..}

Y en mi clase Register.java es donde usar Retrofit con llamada sincrónica

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(); } } }

En la interfaz de 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 ); }

Para el análisis de utilidades de la respuesta InputStream

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


Agregando a la respuesta dada por @insomniac . Puede crear un Map para colocar el parámetro para RequestBody incluida la imagen.

Código para la interfaz

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

Código para la clase Java

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(); } });