web-dev-qa-db-ja.com

問題が発生している@multipartで@bodyを改造する

クラス型オブジェクトの画像マルチパート。

ケース1.(私が行ったもの)

サービスパラメータ:

{"id":"1","name":"vishal","image/file":""} 

そのとき私のAPI/Retrofit

@Multipart
@POST("webservice")
Call<SignUpResp> loadSignupMultipart(@Part("description") RequestBody description, @Part MultipartBody.Part file, @QueryMap HashMap<String, String> params);

ケース2.(問題がある場合)@Body class<UploadwithImage>

{
    "methodName":"submitLevel1Part2Icon",
    "userid":"150",
    "headerData":{
        "fiction":{
            "icon_type":"1",
            "icon_id":"3"},
        "nonfiction":{
            "icon_type":"2",
            "icon_id":"4"},
        "relation":{
            "icon_type":"3",
            "icon_id":"0",
            "name":"Ronak",
            "relative_image":"<File>",
            "relation_id":"3"},
        "self":{
            "icon_type":"4",
            "icon_id":"0"}
    }
}

私はこれを試していますAPI

 @Multipart
 @POST("webservice")
 Call<SubmitLevel1Part2IconResp> loadLevel1halfIconswithImage(@Part("description") RequestBody description, @Part MultipartBody.Part file, @Body UploadwithImage uploadImage);

Java側

    /**
     * code for multipart
     */
     // create RequestBody instance from file
     RequestBody requestFile =  RequestBody.create(MediaType.parse("multipart/form-data"), fileUpload);

     // MultipartBody.Part is used to send also the actual filename
     MultipartBody.Part body =  MultipartBody.Part.createFormData("methodName[headerData][relation][relative_image]", fileUpload.getName(), requestFile);

     // add another part within the multipart request
     String descriptionString = "hello, this is description speaking";
     RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);

    call = service.loadLevel1halfIconswithImage(description, body, levelOneHalfIcons);

理由はわかりませんが、次のようなエラーが返されます。

"@Bodyパラメータはフォームまたはマルチパートエンコーディングでは使用できません"

どんな助けにも感謝します。

9
Vishal Patel

メソッドを次のように変更します

@Multipart
@POST("users/{id}/user_photos")
Call<models.UploadResponse> uploadPhoto(@Path("id") int userId, @PartMap Map<String, RequestBody> params);

次に、リクエストパラメータを作成します。

//All the String parameters, you have to put like
Map<String, RequestBody> map = new HashMap<>();
map.put("methodName", toRequestBody(methodName));
map.put("userid", toRequestBody(userId));
map.put("relation", toRequestBody(relation));
map.put("icon_type", toRequestBody(iconType));
map.put("icon_id", toRequestBody(iconId));
map.put("name", toRequestBody(name));
map.put("relation_id", toRequestBody(relationId));

//To put your image file you have to do
File file = new File("file_name");
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
map.put("relative_image\"; filename=\"some_file_name.png\"", fileBody);

// This method  converts String to RequestBody
public static RequestBody toRequestBody (String value) {
    RequestBody body = RequestBody.create(MediaType.parse("text/plain"), value);
    return body ;
}

//To send your request
call = service.loadLevel1halfIconswithImage(description, params);

PartMapを使用したくない場合は、単にそれらをパラメーターとして渡すことができます。私の答えをチェックしてください https://stackoverflow.com/a/37052548/1320616 リクエストで画像ファイルを送信する際の手がかりを取得します。

9
Ankit Aggarwal

簡単な方法として、私はこのようにしました:

私は tested を変更して

_Call<Result> resultCall = service.uploadImage(body); 
_

Call<Result> resultCall = service.uploadImage(body, result);ここでresult

Result.Java私のAPIのクラス(応答):

_public class Result {

    @SerializedName("result")
    @Expose
    private String result;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @SerializedName("value")
    @Expose
    private String value;

    /**
     * @return The result
     */
    public String getResult() {
        return result;
    }

    /**
     * @param result The result
     */
    public void setResult(String result) {
        this.result = result;
    }

}
_

次のようなオブジェクトを作成しました:

_Result result = new Result();
result.setResult("success");
result.setValue("my value");
_

必要に応じてクラスを変更し、リクエストを送信するときにオブジェクトを渡すことができます。したがって、ApiServiceクラスは次のようになります。

ApiService.Java

_/**
 * @author Pratik Butani on 23/4/16.
 */
public interface ApiService {

    /*
    Retrofit get annotation with our URL
    And our method that will return us the List of Contacts
    */
    @Multipart
    @POST("upload.php")
    Call<Result> uploadImage(@Part MultipartBody.Part file, @Part("result") Result result);

}
_

そして、My PHPコードは:

_<?php

    $file_path = "";
    $var = $_POST['result']; //here I m getting JSON

    $file_path = $file_path . basename( $_FILES['uploaded_file']['name']);
    if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) {
        $result = array("result" => "success", "value" => $var);
    } else{
        $result = array("result" => "error");
    }

    echo json_encode($result);

?>
_

それがあなたを助けることを願っています。ありがとうございました。

9
Pratik Butani

MapRequestBodyとともに値として使用し、文字列をキーとして使用してパラメータを追加することもできます。これをマルチパートとPartMapを使用して送信できます。

次のコードを確認してください。

@Multipart
@POST("/add")
Call<ResponseBody> addDocument(@PartMap Map<String,RequestBody> params);

Map<String, RequestBody> map = new HashMap<>();

map.put("user_id", RequestBody.create(MediaType.parse("multipart/form-data"), SessionManager.getInstance().getCurrentUserId()));
map.put("doc_name", RequestBody.create(MediaType.parse("multipart/form-data"), CommonUtils.removeExtension(textFile.getName())));
map.put("doc_category", RequestBody.create(MediaType.parse("multipart/form-data"), category));
map.put("doc_image_file", RequestBody.create(MediaType.parse("multipart/form-data"), imageFile));
map.put("doc_text_content", RequestBody.create(MediaType.parse("multipart/form-data"), body));
map.put("doc_update_time", RequestBody.create(MediaType.parse("multipart/form-data"), "" + new Date(textFile.lastModified())));
4
user4042384

以下の1つの画像ファイルのように、タイプを指定してマルチパートボディービルダーにすべてのリクエストパラメーターを追加できます。メディアタイプの解析multipart/form-dataを設定し、他のいくつかのパラメーターでメディアタイプの解析text/plainを設定しました。このビルダーは、マルチパートボディを作成するためにビルドし、マルチパートボディのボディアノテーションを使用して送信できます。

@Multipart
@POST("user/update")
Call<ResponseBody> addDocument(@@Part MultipartBody file);


final MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder()
      .setType(MultipartBody.FORM);

requestBodyBuilder.addFormDataPart("doc_image_file", imageFile.getName(),
      RequestBody.create(MediaType.parse("multipart/form-data"), imageFile));
requestBodyBuilder.addFormDataPart("user_id", null, RequestBody.create(MediaType.parse("text/plain"),"12"));
requestBodyBuilder.addFormDataPart("doc_name", null, RequestBody.create(MediaType.parse("text/plain"),"myfile"));
requestBodyBuilder.addFormDataPart("doc_category", null, RequestBody.create(MediaType.parse("text/plain"),category));
requestBodyBuilder.addFormDataPart("doc_image_file", imageFile.getName(),RequestBody.create(MediaType.parse("multipart/form-data"),imageFile));
requestBodyBuilder.addFormDataPart("doc_text_content", null, RequestBody.create(MediaType.parse("text/plain"),body));
RequestBody multipartBody = requestBodyBuilder.build();
2
user4042384

Webブラウザーがマルチパートを実行している方法を追跡するだけです。彼らはネストされたキーを "[]"に入れ、画像にもキーを与えます。

Call<SubmitLevel1Part2IconResp> loadLevel1halfIconswithImage(@Part("headerdata[relation][icon_type]") RequestBody icon_type, @Part("headerdata[relation][name]") RequestBody name, @Part MultipartBody.Part file);

そしてJavaで

 // MultipartBody.Part is used to send also the actual filename
 MultipartBody.Part body =  MultipartBody.Part.createFormData("headerdata[relation][relative_image]", fileUpload.getName(), requestFile);



call = service.loadLevel1halfIconswithImage(icon_type, name, body);
0
andylee

https://www.linkedin.com/Pulse/retrofit-2-how-upload-multiple-files-server-mahesh-gawale

この質問に対する最良の答えはここにあると思います。それは私には完璧に働きました。

これは、Androidでレトロフィットを使用してファイルの配列をアップロードする例です。

これはサービスがどのようになるかです

_public interface ApiService {

    @POST("/event/store")
    Call<ResModel> event_store(@Body RequestBody file);
}
_

これは、Clientクラスがどのように見えるかです

_public class ApiClient   {
    public static final String API_BASE_URL = "api base url";

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(API_BASE_URL).addConverterFactory(GsonConverterFactory.create());

    public static ApiService createService(Class<ApiService> serviceClass)
    {
        Retrofit retrofit = builder.client(httpClient.build()).build();
        return retrofit.create(serviceClass);
    }
}
_

アクティビティやフラグメント、または必要な場所にこのようにアップロードします

_    ApiService service = ApiClient.createService(ApiService.class);

    MultipartBody.Builder builder = new MultipartBody.Builder();
    builder.setType(MultipartBody.FORM);


    builder.addFormDataPart("event_name", "xyz");
    builder.addFormDataPart("desc", "Lorem ipsum");

    // Single Image
    builder.addFormDataPart("files",file1.getName(),RequestBody.create(MediaType.parse("image/*"), file1));

    // Multiple Images 
    for (int i = 0; i <filePaths.size() ; i++) {
            File file = new File(filePaths.get(i));
            RequestBody requestImage = RequestBody.create(MediaType.parse("multipart/form-data"), file);
            builder.addFormDataPart("event_images[]", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
            }


    MultipartBody requestBody = builder.build();
    Call<ResModel> call = service.event_store(requestBody);
    call.enqueue(new Callback<ResponseBody>() {
         @Override
         public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
             Toast.makeText(getBaseContext(),"All fine",Toast.LENGTH_SHORT).show();
         }

         @Override
         public void onFailure(Call<ResponseBody> call, Throwable t) {
            Toast.makeText(getBaseContext(),t.getMessage(),Toast.LENGTH_SHORT).show();
         }
     });
_

注:filePaths.size()は、ピックアップ画像パスの配列リストです。この投稿がお役に立てば幸いです。ここにコメントとしてフィードバックをお寄せください。

0
sahan.perera
Here is my json request format is :
{
"task":{
"category_id":"1",
"price":"10",
"description":"1",
"task_videos_attributes":[
{
"link":"video file goes here",
"size":"100x100"
}
]
}
}



// my request becomes 
 HashMap<String, RequestBody> task = new HashMap();          
  task.put("task[category_id]", createPartFromString(categoryId));
  task.put("task[price]", createPartFromString("" + etPrice.getText().toString()));
            task.put("task[description]", createPartFromString("" + etDescription.getText().toString()));


// for videos file list
  final List<MultipartBody.Part> body = new ArrayList<>();
  for (int i = 0; i < videos.size(); i++) {

 task.put("task[task_videos_attributes][" + i+ "][size]", createPartFromString("100x100"));

 File videoFile = new File(videos.get(i));
                        RequestBody requestBody = RequestBody.create(MediaType.parse("video/mp4"), videoFile);
                        MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("task[task_videos_attributes][" + i + "][link]", videoFile.getName(), requestBody);
                        body.add(fileToUpload);

}


// here is a final call
  new RestClient(this).getInstance().get().postTask(body, task).enqueue(callback);




// This function converts my string to request body
   @NonNull
    private RequestBody createPartFromString(String descriptionString) {
        if (descriptionString == null)
            return RequestBody.create(MultipartBody.FORM, "");
        return RequestBody.create(
                MultipartBody.FORM, descriptionString);

    }

これがあなたに役立つことを願っています...

0
Jatin

これは私にとってはうまくいきます。

私がしたことは、次を使用してすべての追加のパラメータを追加することでした:

MultipartBody.Part Partname = MultipartBody.Part.createFormData("ParamName", "Value");

Mabeあなたは別のボディを作成する必要はありませんが、ファイルや送信しているものとは別に他のパラメーターを追加するだけです。最後に、インターフェイスに、必要なすべてのボディパーツをパラメータとして配置しました。

@Multipart
@POST("api/service/uploadVideo")
Call<ResponseBody> uploadVideoToServer(
        @Part MultipartBody.Part video,
        @Part MultipartBody.Part param2,
        @Part MultipartBody.Part param3 ....
);