2016-04-08 4 views
12

Ich versuche, Datei auf dem Server mit Retrofit2 zu senden. Ich mache alles entsprechend Dokumentation, bekomme aber immer 400 Serverfehler.Retrofit - Multipart Anfrage: Erforderlich MultipartFile Parameter 'Datei' ist nicht vorhanden

ich versucht, wie dies zu tun:

RequestBody body = 
       RequestBody.create(MediaType.parse("image/png"), photo); 
    //.......... 

    @Multipart 
    @POST(ADD_PHOTO) 
    Observable<HPSPhotoResponse> 
    addPhoto(@Part("file") RequestBody file); 

... und wie folgt aus:

MultipartBody.Part part = MultipartBody.Part.createFormData("file", "file", body); 
    //........... 

    @Multipart 
    @POST(ADD_PHOTO) 
    Observable<HPSPhotoResponse> 
    addPhoto(@Part("file") MultipartBody.Part files); 

does't Angelegenheit. Ergebnis ist immer das gleiche "Multipart Anfrage: Erforderlich MultipartFile Parameter 'Datei' ist nicht vorhanden" - Server-Antwort.

Ich würde denken, dass Frühling auf dem Server funktioniert nicht gut, aber ich mache den entsprechenden Code auf Swift (iOS) und es funktioniert! Hier sieht Server diesen 'Datei' Teil.

Alamofire.upload(method, endpoint, headers: headers, 
      multipartFormData: { multipartFormData in 
       multipartFormData.appendBodyPart(fileURL: self.filePath!, name: "file") 
      } 

Jetzt möchte ich es funktioniert auf Android mit Retrofit. Aber ich schaue sogar in Protokolle der Retrofit-Anfragen und in der Tat sehe ich keine 'Datei' Text in den Protokollen.

Was ist daran falsch?

Antwort

23

Sie können den folgenden Beispielcode versuchen. In dieser Demo-App werden wir ein Foto hochladen, nachdem Sie in der Galerie ausgewählt haben. Ich hoffe es hilft!

build.gradle Datei:

dependencies { 
    ... 
    compile 'com.squareup.retrofit2:retrofit:2.0.1' 
    compile 'com.squareup.retrofit2:converter-gson:2.0.1' 
    ... 
} 

WebAPIService.java Datei:

public interface WebAPIService { 

    @Multipart 
    @POST("/api/fileupload") 
    Call<ResponseBody> postFile(@Part MultipartBody.Part file, @Part("description") RequestBody description); 
} 

FileActivity.java Datei:

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

Ja !!! Besten Dank, dass ich :) !!! Es hat geholfen. ... Das Hauptproblem bestand genau im Nachrüsten "... nachrüsten: 2.0.0" statt "..nachrüsten: 2.0.1". In dieser Version stimmt etwas nicht mit der Annotation "MultipartBody.Part" Ich habe es geändert und es hat Arbeit genau wie iOS bekommen. Danke noch einmal. –

+0

Wie Bild mit Parameter senden? Wenn ich Bild mit Parameter dann java.lang.IllegalArgumentException hinzufügen: @Part Parameter, die das MultipartBody.Part verwenden, dürfen keinen Teilnamen in der Annotation enthalten – Suman

+0

@Suman Ich habe nicht mit Retrofit seit Monaten getestet Sie können jedoch versuchen, "@Part (" description ") RequestBody description" als meinen Code oben oder unter http://square.github.io/retrofit/ – BNK

0

In meinem Fall hat der Server einige Header nicht verarbeitet, die nachgerüstet werden. Deshalb musste ich nutzlose Header von Retrofit-Anfragen entfernen. Ich habe wie diese Schnittstellenfunktion erstellt:

@POST("my/files/photo/") 
Call<FileUploadResponse> uploadPhoto(@Header("Content-Type") String contentType, 
              @Header("Authorization") String auth, 
              @Body MultipartBody body); 

Und nennen Sie es mögen:

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

Details siehe hier: Upload picture to server using retrofit 2

Verwandte Themen