在Android中使用改进2上传二进制文件

时间:2016-10-24 09:16:51

标签: android retrofit2

我想在Android中将二进制文件上传到服务器。我通过邮递员测试Api方法:

enter image description here

没关系,你可以看到还有另一个选项可以上传文件作为表格数据(键,值):

enter image description here

每个教程(如this one)都会介绍如何将文件上传为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。

改装存储库中只有一个问题是 How can I POST a image binary in retrofit 2.0 beta? 。我使用它的解决方案:

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. 

我的代码出了什么问题?我该怎么办?

8 个答案:

答案 0 :(得分:4)

经过几个小时的搜索,我发现在上一个示例的代码的API接口中仍然存在@Multipart注释!阻止将二进制数据发送到服务器并且改造存储库中的解决方案没问题!

答案 1 :(得分:2)

在 Kotlin 中,您可以这样做:

val file: File = retrieveMyJavaFile()
val requestBody: RequestBody = file.asRequestBody("application/octet-stream".toMediaTypeOrNull())
val response: MyResponse = myAPI.uploadPhoto(requestBody).body()!!

答案 2 :(得分:1)

只需添加另一种解决方案,因为我必须先深入了解问题中发生的事情。

我的解决方案是直接将二进制文件作为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的原始问题相同,但为清楚起见,我也将这个答案留给下一个读者。

答案 3 :(得分:1)

我遇到了同样的问题,我想上传二进制文件(图像)。该API是Wordpress的

我遵循了this issue

后面给出的解决方案代码

这是我经过修改的代码

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

答案 4 :(得分: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);

答案 5 :(得分:0)

just MediaType ==空 我的代码:

  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>

答案 6 :(得分:0)

我像这样将图像上传到服务器,但在 volley 中,这是我的代码 希望这对某人有帮助

public void uploadImageToServer(byte[] value) {
        final StringRequest stringRequest = new StringRequest(Request.Method.PUT,uploadImageURL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.e("s3 response", response);
                        Toast.makeText(context, "Image Uploaded to Server", Toast.LENGTH_LONG).show();
                       
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("error response", error.toString());
                        Toast.makeText(context, "Image Not Uploaded", Toast.LENGTH_LONG).show();
                    }
                }) {


            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headerMap = new HashMap<String, String>();
                headerMap.put("header1", "header value");
                headerMap.put("header2", "header value");
                headerMap.put("Content-Type", "image/jpeg");
                Log.e("header", headerMap.toString());
                return headerMap;
            }

            @Override
            public byte[] getBody() throws AuthFailureError {
                return value;
            }

        };
        {
            int socketTimeout = 30000;
            RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
            stringRequest.setRetryPolicy(policy);
            RequestQueue requestQueue = Volley.newRequestQueue(this);
            requestQueue.getCache().clear();
            requestQueue.add(stringRequest);
        }
    }

答案 7 :(得分:0)

如果有任何安卓开发者想在 volley 的帮助下使用二进制数据通过服务器上传文件。

public void uploadImageToServer (byte[] imageByte) {
            final StringRequest stringRequest = new StringRequest(Request.Method.POST,uploadImageURL,
                    new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            Log.e("s3 response", response);
                            Toast.makeText(context, "Image Uploaded to Server", Toast.LENGTH_LONG).show();
                           
                        }
                    },
                    new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                            Log.e("error response", error.toString());
                            Toast.makeText(context, "Image Not Uploaded", Toast.LENGTH_LONG).show();
                        }
                    }) {
    
    
                @Override
                public Map<String, String> getHeaders() throws AuthFailureError {
                    Map<String, String> headerMap = new HashMap<String, String>();
                    headerMap.put("header1", "header value");
                    headerMap.put("Content-Type", "image/jpeg");
                    return headerMap;
                }
    
                @Override
                public byte[] getBody() throws AuthFailureError {
               //Binary value data
                    return value;
                }
    
            };
            {
                int socketTimeout = 30000;
                RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                stringRequest.setRetryPolicy(policy);
                RequestQueue requestQueue = Volley.newRequestQueue(this);
                requestQueue.getCache().clear();
                requestQueue.add(stringRequest);
            }
        }



 
//You can convert any file to byte array
 public static byte[] convertFileToBytes(File file)
    {
     int size = (int) userImageFile.length();
        byte[] bytes = new byte[size];
        try {
            BufferedInputStream buf = new BufferedInputStream(new FileInputStream(userImageFile));
            buf.read(bytes, 0, bytes.length);
            buf.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return bytes;
    }