web-dev-qa-db-ja.com

Androidにレトロフィット2でバイナリファイルをアップロードします

Androidのサーバーにバイナリファイルをアップロードしたい。私は郵便配達人によってApiメソッドをテストします:

enter image description here

そして、あなたがファイルをフォームデータ(キー、値)としてアップロードできる別のオプションがあるのを見て、それは問題ありません:

enter image description here

すべてのチュートリアル( これ など)は、ファイルをmultipart/form-dataとしてアップロードする方法を説明しています。

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

    // MultipartBody.Part is used to send also the actual file name
    MultipartBody.Part body =
            MultipartBody.Part.createFormData("picture", file.getName(), requestFile);

私はたくさん検索しましたが、retrofit2でバイナリとしてファイルをアップロードする方法を見つけることができませんでした。

retrofitリポジトリにどうすればよいPOSTレトロフィット2.0ベータの画像バイナリ?。私はそのソリューションを使用します:

APIサービス:

@POST("trip/{tripId}/media/photos")
Call<MediaPost> postEventPhoto(
    @Path("eventId") int tripId,
    @Header("Authorization") String accessToken,
    @Query("direction") String direction,
    @Body RequestBody photo);

発信者:

InputStream in = new FileInputStream(new File(media.getPath()));
byte[] buf;
buf = new byte[in.available()];
while (in.read(buf) != -1);
RequestBody requestBody = RequestBody
    .create(MediaType.parse("application/octet-stream"), buf);
Call<MediaPost> mediaPostCall = tripApiService.postTripPhoto(
    tripId,
    ((GlobalInfo) getApplicationContext()).getApiAccessToken(),
    direction,
    requestBody);

しかし、私はこのエラーを受け取りました:

Java.lang.IllegalArgumentException: @Body parameters cannot be used with form or multi-part encoding. 

私のコードの何が問題になっていますか?私は何をすべきか?

17
Hamed Ghadirian

何時間も検索したところ、@Multipartアノテーションは、最後の例のコードのAPIインターフェイスに残っています!バイナリデータをサーバーに送信することを防ぐため、リポジトリの改造は問題ありませんでした。

4
Hamed Ghadirian

最初の質問で何が起こったかを理解するために少し掘る必要があったので、別の解決策を追加するだけです。

私の解決策は、バイナリファイルをbyte[]として直接取得し、RequestBody内に配置することです。したがって、最終的にはコードは次のようになります。

interface RetrofitService {
    @POST("api/v1/upload_file")
    Call<Void> uploadBinaryFile(@Body RequestBody body);
}

そしてそれを呼び出すには:

public void uploadBinaryFile(File fileToUpload) {
    retrofitService
        .uploadBinaryFile(RequestBody.create(MediaType.parse("application/octet"), 
            Files.readAllBytes(fileToUpload));
}

これは基本的にOPの元の質問と同じですが、明確にするために、この回答も次の読者のために残しておきます。

5
Darwind

同じ問題がありましたが、バイナリファイル(画像)をアップロードしたいと思いました。 APIはWordpressのものでした

この問題 の最後にあるソリューションコードに従いました。

これが私の少し変更されたコードです

@POST("wp-json/wp/v2/media/")
Call<ImagePostResult> postEventPhoto(
        @Header("Authorization") String accessToken,
        @Header("Content-Type") String contentType,
        @Header("Content-Disposition") String contentDisposition,
        @Body RequestBody photo);

こちらがリクエストです

        // For BasicAuth
        String authHeader = getAuthHeader();

        String contentType = "application/binary";
        String contentDisposition = "attachment; filename =  " + fileName;

        RequestBody requestBodyee = null;
        try {
            InputStream in = new FileInputStream(file);

            byte[] buf;
            buf = new byte[in.available()];
            while (in.read(buf) != -1) ;
            requestBodyee = RequestBody
                    .create(MediaType.parse("application/octet-stream"), buf);
        } catch (IOException e) {
            e.printStackTrace();
        }


        Call<ImagePostResult> imagePostResultCall = apiInterface.postEventPhoto(
                authHeader,
                contentType,
                contentDisposition,
                requestBodyee);
        imagePostResultCall.enqueue(new Callback<ImagePostResult>() {
            @Override
            public void onResponse(Call<ImagePostResult> call, Response<ImagePostResult> response) {
                // Response Success
                if (response.isSuccessful()) {
                  // yaay
                }
            }

            @Override
            public void onFailure(Call<ImagePostResult> call, Throwable t) {
                Log.d(TAG, "onFailure: " + t);
            }
        });
1
Makarand

mediaType == Null my code:

  private fun put(uploadUrl : String , localPath : String) {
        val file = File(localPath)
        val byteArray = file2Byte(localPath)!!
        val responseBody = RequestBody.create(null , byteArray)
        val call = HttpFactory.providerUp.up(uploadUrl , responseBody)

        call.enqueue(object : Callback<ResponseBody> {
            override fun onFailure(call : retrofit2.Call<ResponseBody>? , t : Throwable?) {
                LogUtil.toast("Failure")
            }

            override fun onResponse(call : retrofit2.Call<ResponseBody>? , response : retrofit.Response<ResponseBody>?) {
                if (response!!.code() == 200) {
                    LogUtil.toast("YES")
                } else {
                    LogUtil.toast("NO")
                }
            }
        })
    }
@PUT
    fun up2(@Url url : String ,@Body requestBody : RequestBody ) : Call<ResponseBody>
0
朱小药

画像を送信することもできます

//Api Interface

@Part MultipartBody.Part body


//Call in activity
     file = FileUtils.getFile(this, uri);
                            reqFile = RequestBody.create(MediaType.parse("image/*"), file);
                            body = MultipartBody.Part.createFormData("uploaded_file", "Img_" + "_" + rightNow.getTimeInMillis() + ".jpg", reqFile);
0
Rajat Kalia