【问题标题】:Unable to upload picture from Android to java server无法将图片从 Android 上传到 java 服务器
【发布时间】:2018-05-08 07:09:21
【问题描述】:

我一直在尝试通过 Android Retrofit + SpringMVC 实现个人资料照片上传功能。 Java 服务器无法响应 Retrofit API 调用。相关代码sn-p如下:

API接口

@Multipart
@POST("user/profileImage")
Call<ResponseBody> uploadImage(@Part MultipartBody.Part image, @Part("name") RequestBody name);

上传到服务器

public void uploadToServer(){
    //Get retrofit client
    Retrofit retrofit = ApiClient.getClient();
    //Get API interface
    ApiInterface apiInterface = retrofit.create(ApiInterface.class);
    // Get image parts
    MultipartBody.Part imageParts = bitmapToMultipart(imageBitmap);
    //Get image name
    RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "ProfileImage");
    //Call image upload API
    Call<ResponseBody> call = apiInterface.uploadImage(imageParts,name);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            ResponseBody body = response.body();
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            t.printStackTrace();
        }
    });
}

bitmapToMultipart

public MultipartBody.Part bitmapToMultipart(Bitmap imageBitmap){
    File file = null;
    try {
        //create a file to write bitmap data
        file = new File(this.getCacheDir(), "imageBitmap");
        file.createNewFile();

        //Convert bitmap to byte array
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        imageBitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
        byte[] bitmapdata = bos.toByteArray();

        //write the bytes in file
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(bitmapdata);
        fos.flush();
        fos.close();
    }catch(IOException e){
        e.printStackTrace();
    }
    RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
    MultipartBody.Part body = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);

    return body;
}

Java SpringMVC 控制器

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping(value = "/profileImage", method = RequestMethod.POST)
    public  @ResponseBody String imageUploader(@RequestParam("image") MultipartFile image, @RequestBody RequestBody name)throws Exception{
        return "";
    }
}

问题是: 请求甚至没有到达 java 服务器。

【问题讨论】:

  • 你的 bitmapToMultipart() 应该在那个 catch 块中return null;。在调用该函数的地方,您应该检查返回值是否为 null。如果它为空,则不继续。请调整您的代码。
  • 进一步删除 ByteArrayOutputStream 并将您的位图直接压缩为fos
  • file.createNewFile();。删除该行。
  • @greenapps 返回类型必须是 MultipartBody.Part 因为这是 API 参数的返回类型。图片可以在客户端选择并显示,问题是服务器没有响应请求。我认为这对我没有帮助。
  • 是的,我明白了。但它会帮助你使你的代码更健壮。即使对于 MultipartBody.Part 类型,您也可以在那里返回 null 。请添加我要求的所有内容。

标签: java android spring-mvc retrofit


【解决方案1】:

在您的 uploadToServer() 函数中,媒体类型应为“multipart/form-data”,而不是字段名称的“text/plain”...

//Get image name
    RequestBody name = RequestBody.create(MediaType.parse("multipart/form-data"), "ProfileImage");

在您的 bitmapToMultipart() 函数中,媒体类型应为“multipart/form-data”。 (“image/*”也应该可以,但如果不是“multipart/form-data”肯定可以)

参考- How to Upload Image file in Retrofit 2

在你的 spring 控制器中你应该使用@RequestParam 代替@Requestbody

@Controller
@RequestMapping("/user")
public class UserController{
    @RequestMapping(value = "/profileImage", method = RequestMethod.POST)
    public  @ResponseBody String imageUploader(@RequestParam("image") MultipartFile image, @RequestParam String name)throws Exception{
        return "";
    }
}

【讨论】:

    【解决方案2】:

    请更换你的

    RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
    

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

    即你的 bitmapToMultipart 函数应该是这样的,

    public MultipartBody.Part bitmapToMultipart(Bitmap imageBitmap){
        File file = null;
        try {
            //create a file to write bitmap data
            file = new File(this.getCacheDir(), "imageBitmap");
            file.createNewFile();
    
            //Convert bitmap to byte array
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            imageBitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
            byte[] bitmapdata = bos.toByteArray();
    
            //write the bytes in file
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(bitmapdata);
            fos.flush();
            fos.close();
        }catch(IOException e){
            e.printStackTrace();
        }
        RequestBody reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part body = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);
    
        return body;
    }
    

    【讨论】:

      【解决方案3】:

      API接口

      @Multipart
      @POST("user/profileImage")
      Call<ResponseBody> uploadImage(@Part("image") MultipartBody.Part image, @Part("name") RequestBody name);
      

      上传到服务器

      public void uploadToServer(){
          //Get retrofit client
          Retrofit retrofit = ApiClient.getClient();
          //Get API interface
          ApiInterface apiInterface = retrofit.create(ApiInterface.class);
          // Get image parts
          MultipartBody.Part imageParts = bitmapToMultipart(imageBitmap);
          //Get image name
          RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "ProfileImage");
          //Call image upload API
          Call<ResponseBody> call = apiInterface.uploadImage(imageParts,name);
          call.enqueue(new Callback<ResponseBody>() {
              @Override
              public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                  ResponseBody body = response.body();
              }
      
              @Override
              public void onFailure(Call<ResponseBody> call, Throwable t) {
                  t.printStackTrace();
              }
          });
      }
      

      bitmapToMultipart

      public MultipartBody.Part bitmapToMultipart(Bitmap imageBitmap){
      
              ByteArrayOutputStream bos = new ByteArrayOutputStream();
              imageBitmap.compress(Bitmap.CompressFormat.JPEG, 0 /*ignored for PNG*/, bos);
              byte[] bitmapdata = bos.toByteArray();
      
          RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), bitmapdata);
          MultipartBody.Part body = MultipartBody.Part.createFormData("upload", "name", reqFile);
      
          return body;
      }  
      

      Java SpringMVC 控制器

      @Controller
      @RequestMapping("/user")
      public class UserController{
          @RequestMapping(value = "/profileImage", method = RequestMethod.POST)
          public  @ResponseBody String imageUploader(@RequestParam("image") MultipartFile image, @RequestParam String name)throws Exception{
              return "";
          }
      }
      

      【讨论】:

        【解决方案4】:
        1. 首先你应该检查android客户端上传文件是否OK.eg:use compress quality 80

          imageBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);

        2. 更改 MediaType 并在客户端调试 RequestBody 有数据
        3. 在服务器上调试检查接收请求数据

        【讨论】:

          猜你喜欢
          • 2017-05-04
          • 2011-05-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-09-04
          • 2014-06-05
          • 1970-01-01
          相关资源
          最近更新 更多