Retrofit – Solicitud de varias partes: El parámetro "archivo" de MultipartFile no está presente
Estoy intentando enviar el archivo en el servidor usando Retrofit2. Hago todo de acuerdo a la documentación, pero siempre obtiene 400 error de servidor.
Estoy tratando de hacer esto:
- RxAndroid y Retrofit: No se puede crear el adaptador de llamada para io.reactivex.Observable <retrofit2.Response <okhttp3.ResponseBody >>
- Utilizar RxJava para encadenar la solicitud en un solo hilo
- Android: pasar dinámicamente la clase del modelo a retroalimentar la devolución de llamada
- Retrofit 2 Se requiere la anotación del método HTTP (por ejemplo, @GET, @POST, etc.)
- No hay ningún error de este tipo al usar robospice-retrofit y getstream.io
RequestBody body = RequestBody.create(MediaType.parse("image/png"), photo); //.......... @Multipart @POST(ADD_PHOTO) Observable<HPSPhotoResponse> addPhoto(@Part("file") RequestBody file);
… y así:
MultipartBody.Part part = MultipartBody.Part.createFormData("file", "file", body); //........... @Multipart @POST(ADD_PHOTO) Observable<HPSPhotoResponse> addPhoto(@Part("file") MultipartBody.Part files);
No importa El resultado es siempre el mismo "Solicitud de varias partes: El parámetro" archivo "de archivo multipartito necesario no está presente" – respuesta del servidor.
Yo creo que Spring en el servidor no funciona bien, pero hago el código equivalente en Swift (iOS) y funciona! Aquí el servidor ve esta parte del "archivo".
Alamofire.upload(method, endpoint, headers: headers, multipartFormData: { multipartFormData in multipartFormData.appendBodyPart(fileURL: self.filePath!, name: "file") }
Ahora quiero que funcione en Android con Retrofit. Pero incluso buscar en los registros de las solicitudes de Retrofit y de hecho no veo ningún "archivo" de texto en los registros.
¿Qué está mal con eso?
- Prueba de unidad JVM con Mockito para pruebas Retrofit2 y RxJava para solicitudes de red
- ¿Qué está causando HTTP FALLA: java.net.SocketException: Socket cerrado?
- OkHttp3 caché parece estar desmarcada con Retrofit 2
- ¿Cómo usar AutoValue con Retrofit 2?
- ¿Es posible mostrar la barra de progreso cuando se descarga a través de Retrofit 2 Asynchronous?
- Broken Pipe al intentar cargar una actualización de archivo grande 2
- Cómo hacer una solicitud múltiple y esperar hasta que los datos provengan de todas las solicitudes en retrofit 2.0 - android
- Unidad de prueba de la aplicación android con retrofit y rxjava
Puede probar el siguiente código de ejemplo. En esta aplicación de demostración, subiremos una foto después de seleccionarla en la Galería. ¡Espero eso ayude!
Archivo build.gradle :
dependencies { ... compile 'com.squareup.retrofit2:retrofit:2.0.1' compile 'com.squareup.retrofit2:converter-gson:2.0.1' ... }
Archivo WebAPIService.java :
public interface WebAPIService { @Multipart @POST("/api/fileupload") Call<ResponseBody> postFile(@Part MultipartBody.Part file, @Part("description") RequestBody description); }
Archivo FileActivity.java :
... import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; public class FileActivity extends AppCompatActivity { private final Context mContext = this; private final String API_URL_BASE = "http://serverip:port"; private final String LOG_TAG = "BNK"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_file); selectImage(); // selects a photo from Gallery } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK && requestCode == 100) { Uri fileUri = data.getData(); if (fileUri != null) { uploadFile(fileUri); // uploads the file to the web service } } } private void uploadFile(Uri fileUri) { String filePath = getRealPathFromUri(fileUri); if (filePath != null && !filePath.isEmpty()) { File file = new File(filePath); if (file.exists()) { Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL_BASE) .build(); WebAPIService service = retrofit.create(WebAPIService.class); // creates RequestBody instance from file RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file); // MultipartBody.Part is used to send also the actual filename MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile); // adds another part within the multipart request String descriptionString = "Sample description"; RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString); // executes the request Call<ResponseBody> call = service.postFile(body, description); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { Log.i(LOG_TAG, "success"); } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.e(LOG_TAG, t.getMessage()); } }); } } } private void selectImage() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("image/*"); startActivityForResult(intent, 100); } public String getRealPathFromUri(final Uri uri) { // DocumentProvider if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(mContext, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(mContext, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; Uri contentUri = null; if ("image".equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video".equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio".equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?"; final String[] selectionArgs = new String[]{ split[1] }; return getDataColumn(mContext, contentUri, selection, selectionArgs); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { // Return the remote address if (isGooglePhotosUri(uri)) return uri.getLastPathSegment(); return getDataColumn(mContext, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null; final String column = "_data"; final String[] projection = { column }; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { final int index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } } finally { if (cursor != null) cursor.close(); } return null; } private boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } private boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } private boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } private boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); } }