How do I pass a multi part body parameter for rxja

2020-01-23 05:25发布

I have been struggling to figure out how to pass a file via the body of a post request. I tried a couple of things online, but nothing quite matches my use case. Here's the postman screen shot for my server code: enter image description here

So, as you can see "photo" is in the body section as a key (file) and the value is an image file. This is a post request on the whole and returns no response when the query is successful.(just shows the status as created, as you can see from the screenshot)[also note:it requires auth token as header param and userid as path param) The endpoint code :

static final String ENDPOINT_UPLOAD_PROFILE_PHOTO= BuildConfig.BASE_URL
            + "/service-profile/v1/member/photo/{userId}";

Now, I am using the following code block for uploading photo :

@Override
public Single<JSONObject> doUploadPhoto(String userId, File filepath) {

    Rx2ANRequest.MultiPartBuilder post = Rx2AndroidNetworking.upload(ApiEndPoint.ENDPOINT_UPLOAD_PROFILE_PHOTO)
                     .addMultipartFile("photo",filepath)

                     .addHeaders("Authorization", mApiHeader.getFormattedProtectedApiHeader())
                     .addHeaders("content-type", "multipart/form-data")
                     .setPriority(Priority.HIGH)

                     .addMultipartParameter("photo",filepath.getAbsolutePath())
                     .addPathParameter("userId",userId);


    return post.build()
            .getObjectSingle(JSONObject.class);

}

Now I reference this in my presenter as follows:

        File file = new File(AppPreferencesHelper.getInstance().getPhotoFile());
//preferences has the path of the file , something like : /storage/emulated/0/DCIM/1566415330315.jpg 

getCompositeDisposable().add(getDataManager().updateCurrentUserPhotoUploadApiCall(file)
                    .subscribeOn(getSchedulerProvider().io())
                    .observeOn(getSchedulerProvider().ui())
                    .subscribe(response -> {

                        Log.d("fileupload", "it is successful" + response);
                        if (!isViewAttached()) {
                            return;
                        }

                    }, throwable -> {
                        if (!isViewAttached()) {
                            return;
                        }
                        Log.d("fileupload", "error: ");

                        getMvpView().hideLoading();

                        // handle the profile retrieval error here
                        //getMvpView().showDialog(R.string.unknown_error, R.string.unknown_error_message);

                        if (throwable instanceof ANError) {
                            ANError anError = (ANError) throwable;
                            Log.d("fileupload", "error: " + anError.getErrorCode());

                            handleApiError(anError);
                        }
                    }));

here's my api call :

@Override
    public Single<JSONObject> updateCurrentUserPhotoUploadApiCall(File file) {
        return mApiHelper.doUploadPhoto(mPreferencesHelper.getCurrentUserId(), file);
    }

Upon trying to upload the image, i get the response : fileupload: error: 400 while filepath and everything seems to be correct. (filepath is : /storage/emulated/0/DCIM/1566415330315.jpg)

Any idea what I am doing wrong? I also, tried post request(without multipart and just passing filepath instead as a body param such that :

Rx2ANRequest.PostRequestBuilder post = Rx2AndroidNetworking.post(processUrl(ApiEndPoint.ENDPOINT_UPLOAD_PROFILE_PHOTO)) // Please note : processUrl(ApiEndPoint.ENDPOINT_UPLOAD_PROFILE_PHOTO)) = https://myapps.com/service-profile/v1/member/photo/{userId}
                .addHeaders("Authorization", mApiHeader.getFormattedProtectedApiHeader())
                .addPathParameter("userId", userId)
          .addBodyParameter("photo",filepath.getAbsolutePath());

but didn't have any luck. it doesn't even show me success or error for the post request when I pass file as a body param. Any idea what I could be missing?

postman works as expected and it recommends the following okhttp client code for java:

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
RequestBody body = RequestBody.create(mediaType, "------WebKitFormBoundary7MA4YWxkTrZ\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"1ab6ef77b355e9acd7cc9b82b5c8ec4f.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");
Request request = new Request.Builder()
  .url("https://myapps.com/api/service-profile/v1/member/photo/9ea899b8-b271-486b-ae64-443a17f06a39")
  .post(body)
  .addHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
  .addHeader("Content-Type", "application/x-www-form-urlencoded")
  .addHeader("Authorization", "Bearer eyJraWQiOiJXZ3NucHRZekZYMnZsRTJ2TEJlUFpjSlJ4TU93SFRqcGkydDZAwdW03bzU5d2xRTFkxUU1HMGg3Iiwic2NwIjpbIm9mZmxpbmVfYWNjZXNzIiwicHJvZmlsZSIsIm9wZW5pZCIsIm1lbWJlciIsImVtYWlsIl0sInN1YiI6InZhcmFuaGErd3BkZXZsYUBjbnZ3cC5jb20iLCJtZW1iZXIucmVhZCI6dHJ1ZSwibWVtYmVyLndyaXRlIjp0cnVlfQ.LQhea6roQyQNIRnb3XWVuQZjoid2yn7TT-cgbdDeUnbMCUtFnOiHKPOLo_zpRr0bB429-yuLeSLdLjj_mF-PESbr0SfvNj01N-AWtYvyn9gEvcqS3hHHzPI44RDYkU8CtenByxwDBLUTlrdAGW7Xmi-UtGdd2_kaM8zkZoVWRS8dbymCVfZyoYr7DeR9hFZtD8RCtYRMRJrgQGZoMv7_1oCJyo8lAWuMpUmZfsEscOOw44hFoNADv221l70mbTIb-XwA")
  .addHeader("User-Agent", "PostmanRuntime/7.15.2")
  .addHeader("Accept", "*/*")
  .addHeader("Cache-Control", "no-cache")
  .addHeader("Postman-Token", "3f81374d-d895-4a55-9122-297,3ff3b3f8-7149-46b9-887e-db1b4")
  .addHeader("Host", "myapps.com")
  .addHeader("Cookie", "AWSALB=HKdluG7WMh8PQmgNrYwRK+fpDEAE3DKnRQXIWOngg7Tn9kzEy5lQWhSsU45P7aLxk7Y")
  .addHeader("Accept-Encoding", "gzip, deflate")
  .addHeader("Content-Length", "17805")
  .addHeader("Connection", "keep-alive")
  .addHeader("cache-control", "no-cache")
  .build();

Response response = client.newCall(request).execute();

I am just wondering how to make sense of this "post(body) content to upload selected jpg image from my device? Also, it would be great if anyone can modify my existing androidnetworking (rx2) code to work as per postman recommendations.

1条回答
一纸荒年 Trace。
2楼-- · 2020-01-23 05:51

Try this.I made it based on your postman request query, pretty sure it will work.

 OkHttpClient okHttpClient = new OkHttpClient();

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
            builder.addFormDataPart("photo", filepath.getAbsolutePath());

            String url = ApiEndPoint.ENDPOINT_UPLOAD_PROFILE_PHOTO;
        RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpeg"), filepath);
        builder.addFormDataPart("photo", filepath.getName(), fileBody);
        RequestBody requestBody = builder.build();
        Request request = new Request.Builder()
                .url(processUrl(url))
                .addHeader("Authorization",mApiHeader.getFormattedProtectedApiHeader())
                .post(requestBody)
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback(){
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("OkHttp1", "onFailure: "+e.toString());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                ResponseBody body = response.body();
                if (body != null) {
                    Log.e("OkHttp1", "onResponse: " + body.string());
                } else {
                    Log.e("OkHttp1", "onResponse: null");
                }
            }
        });
查看更多
登录 后发表回答