简体   繁体   English

如何使用Retrofit2将照片上传到服务器

[英]How to Upload a photo using Retrofit2 to server

Does anyone know an way to upload image to server using retrofit 2. Most of the online solution are using retrofit 1. 有谁知道使用改造2将映像上传到服务器的方法。大多数在线解决方案都使用改造1。

thanks I tried this: 谢谢我尝试了这个:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    //GALLERY
    if ((isGalleryCalled(requestCode) && resultCode == RESULT_OK)) {
        Log.w(TAG, "onActivityResult > isGalleryCalled > data.getData(): " + data.getData());
        Uri originalUri = data.getData();
        if (originalUri != null) {
            mImageUri = originalUri;
        }
    }
    //CAPTURE
    else if ((isCaptureCalled(requestCode)) && resultCode == RESULT_OK) {
        Log.w(TAG, "onActivityResult > isCaptureCalled > data.getData(): " + data.getData());
        Uri originalUri = data.getData();
        if (originalUri != null) {
            mImageUri = originalUri;

        }
    }



private void prepareImage(String mImageUri ) {

    File file = new File(mImageUri );

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

    isUploadImage = true;
    Log.d(TAG, "isUploadImage: " + isUploadImage + " | \nuri: " + uri + " | \nfile getPath: " + file.getPath());

}//end sendReport




    Call<DefaultResponse> call = RestClient.get().uploadImage(file);

....


    @Multipart
    @POST(Constant.API_UPLOADIMAGE)
    Call<DefaultResponse> uploadImage(
            //Upload File
            @Part("myfile\"; filename=\"image.png\" ") RequestBody file
    ); 

I get these errors: 我得到这些错误:

sendErrorReport - file: com.squareup.okhttp.RequestBody$3@2f83a2f9
stat failed: ENOENT (No such file or directory) : content:/media/external/images/media/2720
java.io.FileNotFoundException: content:/media/external/images/media/2720: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:456)
at java.io.FileInputStream.<init>(FileInputStream.java:76)
at okio.Okio.source(Okio.java:163)
at com.squareup.okhttp.RequestBody$3.writeTo(RequestBody.java:117)
at com.squareup.okhttp.MultipartBuilder$MultipartRequestBody.writeOrCountBytes(MultipartBuilder.java:277)
at com.squareup.okhttp.MultipartBuilder$MultipartRequestBody.writeTo(MultipartBuilder.java:297)

[UPDATE] [UPDATE]

Update code from feed back from @Anton Shkurenko 更新@Anton Shkurenko反馈的代码

image path begin processed 图像路径开始处理

UtilApiHelp.getPath: /storage/emulated/0/DCIM/Camera/20151210_124246.jpg UtilApiHelp.getPath:/storage/emulated/0/DCIM/Camera/20151210_124246.jpg

private void prepareImage(String uri) {


    File file = new File(uri);

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

    isUploadImage = true;
    Log.d(TAG, "prepareImage isUploadImage: " + isUploadImage + " | \nuri: " + uri + " | \nfile getPath: " + file.getPath());


    sendErrorReport("", mRequestBodyImage);// test1
uploadImage(file.getPath());//test 2
}//end sendReport



//API Send Image test 1 - FAILED
private void sendErrorReport(String s, String msg, RequestBody file){

    Log.e(TAG, "sendErrorReport - file: " + file.toString());

    String user_id = Preferences.getInstance().getUserId();

    Call<DefaultResponse> call = RestClient.get().sendErrorReport(s, file);
    call.enqueue(new Callback<DefaultResponse>() {
        @Override
        public void onResponse(Response<DefaultResponse> response, Retrofit retrofit) {

            Log.w("sendErrorLog > onResponse => ", String.valueOf(response.isSuccess()));

        }

        @Override
        public void onFailure(Throwable t) {
            t.printStackTrace();
        }
    });
}

error: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 3 column 2 path $ 错误:com.google.gson.JsonSyntaxException:java.lang.IllegalStateException:预期为BEGIN_OBJECT,但位于第3行第2列路径$

//Upload test 2 -> not working
private void uploadImage(final String path) {


    final RequestBody photo =
            UtilApiHelp.getImageBodyBuilder(new HashMap<String, String>() {{
                put("image", path);
            }})
                    //.addFormDataPart("here_you_can_add_another_form_data", anotherFormData)
                    .build();


    Call<DefaultResponse> call = RestClient.get().sendErrorReport(photo);
    call.enqueue(new Callback<DefaultResponse>() {
        @Override
        public void onResponse(Response<DefaultResponse> response, Retrofit retrofit) {

        }

        @Override
        public void onFailure(Throwable t) {
            t.printStackTrace();
        }
    });
}

Error: Caused by: java.lang.IllegalArgumentException: @Body parameters cannot be used with form or multi-part encoding. 错误:原因:java.lang.IllegalArgumentException:@Body参数不能与表单或多部分编码一起使用。 (parameter #1) for method APIService.sendErrorReport (参数#1)用于方法APIService.sendErrorReport

used this call 用了这个电话

@FormUrlEncoded
@POST(Constant.API_POST_error_log)
Call<DefaultResponse> sendErrorReport(@Body RequestBody multipartBody);

[UPDATE] [UPDATE]
Since you updated the question. 自从您更新了问题。 You just can't find the file from given Uri. 您只是无法从给定的Uri中找到文件。 Use the util function getPath from my code to get image path, hope this will work. 使用我的代码中的util函数getPath来获取图像路径,希望getPath起作用。

[OLD SOLUTION] [旧解决方案]
I had this working solution: 我有这个工作的解决方案:

Util functions: 实用功能:

public static RequestBody getImageBody(Map<String, String> map) {
  return getImageBodyBuilder(map).build();
}

public static MultipartBuilder getImageBodyBuilder(Map<String, String> map) {

  MultipartBuilder builder = new MultipartBuilder().type(MultipartBuilder.FORM);
  for (String key : map.keySet()) {
    final String filePlace = map.get(key);
    Log.d(TAG, "File place: " + filePlace);
    final String[] args = filePlace.split("\\.");
    final String fileExt = args[args.length - 1];
    Log.d(TAG, "File extension: " + fileExt);

    // Old solution, porting from one project to another
    // It's about problems with jpeg
    builder.addPart(Headers.of("Content-Disposition",
        "form-data; name=\"" + key + "\"; filename=\"" + filePlace + "\""), RequestBody.create(
        MediaType.parse("image/" + fileExt.toLowerCase().replace("jpg", "jpeg")),
        new File(map.get(key))));
  }

  return builder;
}

public static String getPath(Context ctx, Uri uri) {
  String[] projection = { MediaStore.Images.Media.DATA };
  Cursor cursor = ctx.getContentResolver().query(uri, projection, null, null, null);
  if (cursor == null) return null;
  int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
  cursor.moveToFirst();
  String s = cursor.getString(columnIndex);
  cursor.close();
  return s;
}

Photo uploading. 照片上传。

final RequestBody photo =
    ImageUploadUtils.getImageBodyBuilder(new HashMap<String, String>() {{
                put("photo", imagePathWhateverYouWant);
              }})
              .addFormDataPart("here_you_can_add_another_form_data", anotherFormData).build();

 mApiService.attachPhoto("Token " + getToken(), photo);

ApiService.java (interface): ApiService.java(接口):

// I user here RxJava, but I think it's easy to use Calls here.
@POST("deliveries/photos") Observable<Map<String, String>> attachPhoto(
     @Header("Authorization") String token, 
     @Body RequestBody multipartBody);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM