10

単一の画像をアップロードすることは、レトロフィット 2 では問題ないようです。

ただし、同時に2つの画像をアップロードする方法がわかりません。

ドキュメントに従った場合: http://square.github.io/retrofit/2.x/retrofit/retrofit2/http/PartMap.html

File file = new File(path, "theimage");
File file2 = new File(path2, "theimage");
RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);
RequestBody requestBody2 = RequestBody.create(MediaType.parse("image/png"), file2);
Map<String, RequestBody> params = new HashMap<>();
params.put("image2", requestBody2 );

Call<ResponseBody> call = service.upload(requestBody, params);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
    Log.v("Upload", "success");
}

インターフェース:

public interface FileUploadService {

    @Multipart
    @POST("/upload")
    Call<ResponseBody> upload(
        //@Part("image_logo\"; filename=\"image.png\" ") RequestBody file,
        @Part("file") RequestBody file,
        @PartMap Map<String, RequestBody> params
     //  @Part("description") String description
);

これにより「アップロード:成功」が表示されますが、サーバー側では意味不明になります:

CONTENT_TYPE: マルチパート/フォームデータ; 境界= 50fbfeb3-3abc-4f15-b130-cdcb7e3a0e4f

CONTENT POST:Array ( [file] => �PNG IHDR L alotofbinarygibberish.... ... snip [file2] => �PNG IHDR L more binary gibberish...

誰かが私を正しい方向に向けることができますか?

単一のアップロードは機能するので問題ありません。2 つ以上の画像をアップロードしようとしています。


これに変更すると:

HashMap<String, RequestBody> partMap = new HashMap<String, RequestBody>();
partMap.put("file\"; filename=\"" + file.getName(), requestBody);
partMap.put("file\"; filename=\"" + file2.getName(), requestBody);
Call<ResponseBody> call = service.upload(partMap);

@Multipart
@POST("/upload")
Call<ResponseBody> upload(
    @PartMap() Map<String, RequestBody> partMap,

意味不明なのに2枚目の画像しかアップされてない…!?


アップデート

このRetrofit(2.0 beta2) Multipart file upload does not workソリューションを試しましたが、@body can't me used with multipart: Java.lang.IllegalArgumentException: @Body parameters cannot be used with form or multi-part encoding. (パラメータ #1)

        for (String key : keys) {
            Bitmap bm = selectedImages.get(key);
            File f = new File(saveToInternalStorage(bm, key), key);
            if (f.exists()) {
                buildernew.addFormDataPart(key, key + ".png", RequestBody.create(MEDIA_TYPE, f));
            }
        }
        RequestBody requestBody = buildernew.build();

-

Call<ResponseBody> upload(
    @Body RequestBody requestBody
4

3 に答える 3

7

これは機能します:

            final MediaType MEDIA_TYPE=MediaType.parse("image/png");
            HashMap<String,RequestBody> map=new HashMap<>(selectedImages.size());
            RequestBody file=null;
            File f=null;
            Set<String> keys = selectedImages.keySet();
            for (String key : keys) {
                try {
                    Bitmap bitmap = selectedImages.get(key);
                    f = new File(saveToInternalStorage(bitmap, key), key);

                    FileOutputStream fos = new FileOutputStream(f);
                    if(bitmap!=null){
                        bitmap.compress(Bitmap.CompressFormat.PNG, 0 , fos);
                        fos.flush();
                        fos.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return;
                }

                file=RequestBody.create(MEDIA_TYPE, f);
                map.put(""+key+"\"; filename=\""+key+".jpg",file);
                Log.i("##MYLOG###", "### MAP PUT:" + key + " filename:"+key+".jpg file:" + file.toString() +" type:"+ file.contentType() );
                file=null;
                f = null;
            }

--

Call<ResponseBody> upload(
        @PartMap() Map<String,RequestBody> mapFileAndName //for sending multiple images

--

注意: httpClient.interceptors() でこれをデバッグしている間、私は単一のアップロードしか見ませんでしたが、エンドポイント自体をチェックして実際に取得したものを確認すると、複数のアップロードを取得しました!

于 2016-01-14T14:51:28.580 に答える
2

遅れるかもしれませんが、私の回答は将来の訪問者に役立つかもしれません

次のように複数の画像を選択するようにユーザーに求めています。

int PICK_IMAGE_MULTIPLE = 1;    
Intent intent = new Intent();
       intent.setType("image/*");
       intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
       intent.setAction(Intent.ACTION_GET_CONTENT);
       startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_MULTIPLE);

次に、onActivityResult()私はこれをやっています:

ArrayList<String> filePaths;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE_MULTIPLE) {
        if (data != null) {
            filePaths=new ArrayList<>();
            // If data.getData() == null means multiple images selected, else single image selected.
            if (data.getData() == null) {
                ClipData clipData = data.getClipData();
                if (clipData != null) {
                    for (int i = 0; i < clipData.getItemCount(); i++) {
                        ClipData.Item item = clipData.getItemAt(i);
                        Uri uri = item.getUri();
                        filePaths.add(FileUtils.getPath(Activity.this, uri));
                    }
                }
            } else {
                filePaths.add(FileUtils.getPath(Activity.this,data.getData()));
            }
            sendToServer();
        }
    }
}

このGithubリンクFileUtilsからクラスを取得できます

私のsendToServer()方法は次のようになります。

private void sendToServer() {
    if(filePaths!=null) {
        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
        MediaType MEDIA_TYPE_IMG = MediaType.parse("image/jpeg");
        MultipartBody.Builder builder=new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        RequestBody requestBody;
        try {
            for (int i = 0; i < filePaths.size(); i++) {
                File file = new File(filePaths.get(i));
                requestBody=RequestBody.create(MEDIA_TYPE_IMG,file);
                builder.addFormDataPart("photo"+i,file.getName(),requestBody);
            }
            RequestBody finalRequestBody=builder.build();
            Call<YourResponse> call=apiService.addEvent(finalRequestBody);
            call.enqueue(new Callback<YourResponse>() {
                @Override
                public void onResponse(Call<YourResponse> call, Response<YourResponse> response) {
                    // process response
                }

                @Override
                public void onFailure(Call<YourResponse> call, Throwable t) {
                    t.printStackTrace();
                    t.getCause();
                }
            });
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

最後に、Retrofit エンドポイントは次のようになります。

@POST("event/add")
Call<YourResponse> addEvent(@Body RequestBody body);

応答を処理するためのカスタムモデルクラスにすることも、モデルクラスを作成したくない場合はYourResponse生のクラスを使用することもできます。Response

これが新しい訪問者に役立つことを願っています。

于 2016-06-01T05:14:42.077 に答える