2016-04-08 26 views
12

Retrofit2'yi kullanarak sunucuya dosya göndermeye çalışıyorum. Her şeyi belgelere göre yapıyorum, ancak her zaman 400 sunucu hatası alıyorum.Retrofit - Multipart istek: Gerekli MultipartFile parametresi 'dosya' mevcut değil

böyle yapmaya çalıştım ediyorum:

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

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

... ve bunun gibi:

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

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

does't konuyu. Sonuç her zaman aynıdır "Çoklu talep: Gerekli MultipartFile parametresi 'dosyası' mevcut değil - sunucu yanıtı.

Sunucudaki ilkbaharın iyi çalıştığını düşünmüyorum ama Swift (iOS) üzerinde eşdeğer kodu yapıyorum ve işe yarıyor! Burada Sunucu bu 'dosya' bölümünü görüyor.

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

Şimdi Android'de Retrofit ile çalışmasını istiyorum. Ancak, Retrofit isteklerinin günlüklerine bakıyorum ve aslında günlüklerde herhangi bir 'dosya' metni göremiyorum.

Bunun nesi var?

cevap

23

Aşağıdaki örnek kodu deneyebilirsiniz. Bu demo uygulamasında, Galeri'den seçtikten sonra bir fotoğraf yükleyeceğiz. Umarım yardımcı olur!

build.gradle dosyası:

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

WebAPIService.java dosyası:

public interface WebAPIService { 

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

FileActivity.java dosyası:

... 
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

Evet !!! En büyük teşekkürler ki ben :) !!! Yardım etti. ... Asıl sorun tam olarak "retrofit: 2.0.0" yerine "..retrofit: 2.0.1" uyarlamasıydı. Bu sürümde "MultipartBody.Part" no'lu ek açıklamada yanlış bir şey var ve bende iOS gibi çalıştım. Tekrar teşekkürler. –

+0

Parametre ile görüntü nasıl gönderilir? Parametre ile görüntü eklediysem java.lang.IllegalArgumentException: @Parch parametrelerinin MultipartBody.Part kullanılarak eklenmesi, ek açıklamada bir parça adı içermemelidir – Suman

+0

@Suman Aylarca retrofit ile test edilmedim Ancak, yukarıdaki @ kodumda veya @ http://square.github.io/retrofit/ – BNK

0

Benim durumumda sunucu, güçlendirme gönderen bazı başlıkları kullanmıyordu. Bu yüzden, uyarlama taleplerinden faydasız başlığı kaldırmam gerekiyordu.

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

Ve gibi çağrı: Böyle arayüz fonksiyonu oluşturduk

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

DETAYLAR burada: Upload picture to server using retrofit 2

İlgili konular