【问题标题】:Retrofit 2 Multipart POST request sends extra quotes to PHPRetrofit 2 Multipart POST 请求向 PHP 发送额外的引号
【发布时间】:2016-04-28 03:00:31
【问题描述】:

使用Retrofit 2.0.1,在我的Android App中定义的API接口中有一个调用函数:

@Multipart
@POST("api.php")
Call<ResponseBody> doAPI(
  @Part("lang") String lang,
  @Part("file\"; filename=\"image.jpg") RequestBody file
);

我这样发送请求:

调用 call = service.doAPI("eng", imageFile);

其中imageFile 是使用File 对象创建的RequestBody。上传图片部分没有问题,而@Part("lang") String lang 部分在服务器中得到了额外的引号。

在PHP端是这样写的:

$lang = trim($_POST['lang']);

返回"eng"。为什么字符串周围多了一个双引号?

当然我可以去掉尾随和前导双引号,但这样做很奇怪


相关问题:https://github.com/square/retrofit/issues/1210

【问题讨论】:

  • 如果你的项目使用Retrofit 2, IMO,你可以在stackoverflow.com/questions/36491096/…看到我的回答,请关注Call&lt;ResponseBody&gt; postFile(@Part MultipartBody.Part file, @Part("description") RequestBody description);
  • 是的,使用 Retrofit 2。是否需要使用 MultipartBody.Part ?因为RequestBody 也适用于文件上传。有什么区别?
  • 尝试使用另一个转换器作为文档,Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
  • 是的,我也在问题中发布了链接。可能是一个错误。
  • 这是这个“bug”的正确解决方案:stackoverflow.com/a/36216137/2557258

标签: php android multipartform-data multipart retrofit2


【解决方案1】:

对于您的问题,请作为文档使用

标量(基元、盒装和字符串): com.squareup.retrofit2:converter-scalars

所以,将compile 'com.squareup.retrofit2:converter-scalars:2.0.1' 添加到build.gradle 文件中

那么……

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(API_URL_BASE)
    .addConverterFactory(ScalarsConverterFactory.create())
    //.addConverterFactory(GsonConverterFactory.create())
    .build();

希望对你有帮助!

【讨论】:

  • 这个新的转换器工厂是否支持其他以前的 gson 相关或 FormUrlEncoded 请求,或者我们是否需要将所有请求转换为 Mutipart 类型。希望你明白我的意思
  • java.lang.IllegalArgumentException: 无法为类创建转换器
  • @BNK 那么逻辑在哪里呢?在这个答案中,您建议使用 ScalarsConverterFactory。我试了一下,得到了 IllegalArgumentException。然后你让我使用 GsonConverterFactory。非常聪明。
  • @Yazon2006 ScalarsConverterFactory 是针对 OP 的问题。不知道你有没有同样的问题。该链接适用于IllegalArgumentException,我认为您可以在那里找到有效的答案。当然,我没有你聪明!
【解决方案2】:

对所有参数使用RequestBody。请看下面的代码!!

File file = new File(imagePath);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part imageFileBody = MultipartBody.Part.createFormData("media", file.getName(), requestBody);
RequestBody id = RequestBody.create(MediaType.parse("text/plain"),addOfferRequest.getCar_id());
ApiCallback.MyCall<BaseResponse> myCall = apiRequest.editOfferImage(imageFileBody,id);

使用RetrofitRequestBody 类而不是字符串

@Multipart
@POST(ApiURL)
ApiCallback.MyCall<BaseResponse> editOfferImage(@Part MultipartBody.Part imageFile,@Part("id") RequestBody id);

【讨论】:

    【解决方案3】:

    我今天在我的项目中遇到了这个问题,这就是我解决它的方法。我将字符串上的@Part 和其他原始值更改为@Query,对于文件(在我的情况下为图像)我使用了@Part。与@Part 相比,@Query 处理字符串的方式似乎不同。

    所以我对原始问题的回答如下:

    @Multipart
    @POST("api.php")
    Call<ResponseBody> doAPI(
      @Query("lang") String lang,
      @Part("file\"; filename=\"image.jpg") RequestBody file
    );
    

    这应该发送不带多余引号的字符串值。 遗憾的是,我无法解释为什么会这样,它与数据的@Part 编码有关。

    【讨论】:

    • 谢谢你救了我。我在过去四个小时内就遇到了这个问题,在这个页面的最底部,这个答案解决了这个问题。再次感谢
    • 这是一个很好的答案,因为更改核心改造可能会也可能不会改变您项目中的其他内容(至少您会担心测试)
    【解决方案4】:

    如果您不想使用转换器,以下是我发送包含图像文件和 2 个字符串的多部分请求的方法:

    @Multipart
    @POST("$ID_CHECK_URL/document")
    fun postMultipart(@Part imageFile: MultipartBody.Part, @Part string2:  MultipartBody.Part, @Part string2:  MultipartBody.Part)
    

    这样称呼它:

        val body = RequestBody.create(MediaType.parse("image/jpg"), file)
        val imageFilePart = MultipartBody.Part.createFormData("file", file.name, reqFile)
    
        val string1Part = MultipartBody.Part.createFormData("something", "string 1")
    
        val string2Part = MultipartBody.Part.createFormData("somethingelse", "string 2")
    
        service.postDocument(imageFilePart, string1Part, string2Part)
    

    【讨论】:

    • 我也不想使用转换器,我很高兴这对我有用。谢谢陌生人
    猜你喜欢
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多