android - form - upload files retrofit2
Actualización-Solicitud multiparte: el parámetro requerido ''Archivo'' multiparte no está presente (2)
En mi caso, el servidor no estaba manejando algunos encabezados que la actualización está enviando. Es por eso que tuve que eliminar el encabezado inútil de las solicitudes de modificación. He creado una función de interfaz como esta:
@Multipart
@POST("my/files/photo/")
Call<FileUploadResponse> uploadPhoto(@Header("Content-Type") String contentType,
@Header("Authorization") String auth,
@Part MultipartBody body);
Y llámalo así:
ApiClient.ApiInterface client = ApiClient.getClient();
File file = new File(getPathFromUri(fileUri));
RequestBody fileBody = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
MultipartBody body = new MultipartBody.Builder().addFormDataPart("file-type", "profile")
.addFormDataPart("photo", "image.png", fileBody)
.build();
client.uploadPhoto("multipart/form-data; boundary=" + body.boundary(),
PrefManager.getInstance().getToken(), body);
ver detalles aquí: Cargue la imagen al servidor usando la actualización 2
Estoy tratando de enviar archivos en el servidor usando Retrofit2. Hago todo de acuerdo con la documentación, pero siempre obtengo un error de servidor 400.
Estoy intentando hacer esto:
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 multiparte: el parámetro obligatorio MultipartFile ''file'' no está presente" - respuesta del servidor.
¡Pensaría 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 de ''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 busco en los registros de solicitudes de modificación y, de hecho, no veo ningún texto de "archivo" en los registros.
¿Qué está mal con eso?
Puede probar el siguiente código de muestra. En esta aplicación de demostración, cargaremos una foto después de seleccionarla desde 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());
}
}