%3F而不是我的Retrofit网址中的问号

时间:2016-04-05 06:55:50

标签: android retrofit2

我试图将图片发送到服务器。我的网址包含有关手机的一些参数:

api/v2/user/email_register%3F_height=1184&_target=android/2&_width=768 

这是工作变体:

api/v2/user/email_register?_height=1184&_target=android/2&_width=768

(没有刺激%3?代码)

另外,我试图在@Body中传递我的照片:

@POST("/{url}")
Observable<UpdateUserInfoPayload> register(
        @Header("x-device-id") String deviceId,
        @Body RequestBody requestBody,
        @Path(value = "url", encoded = true) String  method
);

使用MultipartBuilder创建它:

protected RequestBody buildAvatar(String avatarPath) {


 MultipartBuilder builder = new MultipartBuilder()
  .type(MultipartBuilder.FORM)
  .addFormDataPart(ParkApiUrl.PARAM_USER_NAME, name.getText().toString())
  .addFormDataPart(ParkApiUrl.PARAM_USER_SECOND_NAME, lastName.getText().toString())
  .addFormDataPart(ParkApiUrl.PARAM_EMAIL, email.getText().toString())
  .addFormDataPart(ParkApiUrl.PARAM_USER_ENCODED_PASSWORD,
   PasswordUtils.encodePassword(encodePassword()))
  .addFormDataPart(ParkApiUrl.PARAM_USER_GENDER,
   male.isChecked() ? EmailProfile.GENDER_MALE : EmailProfile.GENDER_FEMALE)
  .addFormDataPart(ParkApiUrl.PARAM_PARSE_ID,
   ParseInstallation.getCurrentInstallation().getObjectId());


 File file = new File(avatarPath);;
 int size = (int) file.length();
 byte[] bytes = new byte[size];
 try {
  BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
  buf.read(bytes, 0, bytes.length);
  buf.close();
  builder.addFormDataPart("photo", "image.jpg", RequestBody.create(MEDIA_TYPE_JPG, bytes));
 } catch (IOException e) {
  e.printStackTrace();
 }
 return builder.build();
}

这就是为什么我无法使用例如:

@FieldMap Map<String, String> params

将参数传递给那里,因为@FieldMap需要@FormUrlEncoded而我无法使用@FormUrlEncoded制作@Body请求。

1)如何从我的URL字符串中删除%3F? (改造之外的每一件事都很好!)

2)有没有简单的方法来发送图片?

UPD:  &lt; - 403 Forbidden https://api.example.com/api/v2/user/5984/validate_password 当我使用@Field注释时:

@FormUrlEncoded
@POST("/{url}")
Observable<BooleanResponse> validatePassword(
        @Header("x-device-id") String deviceId,
        @Field(ParkApiUrl.PARAM_USER_ENCODED_PASSWORD) String password,
        @Field(ParkApiUrl.PARAM_HEIGHT) String height,
        @Field(ParkApiUrl.PARAM_WIDTH) String width,
        @Field(ParkApiUrl.PARAM_TARGET) String target,

        @Path(value = "url", encoded = true) String  method
);

当我像这样使用它时,一切都有效:

@FormUrlEncoded
    @POST("/api/v2/user/5984/validate_password?_height=1184&_target=android%2F2&_width=768&_user_id=5984") //full url
    Observable<BooleanResponse> validatePassword(
            @Header("x-device-id") String deviceId,
            @Field(ParkApiUrl.PARAM_USER_ENCODED_PASSWORD) String password
    );

我要删除%3F或了解如何在POST请求中使用Field而不获取FORBIDDEN

4 个答案:

答案 0 :(得分:3)

Retrofit不允许您将查询字符串放在路径中。请查看专为此设计的@QueryMap

答案 1 :(得分:1)

作为参考:https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/QueryMap.html

我使用@QueryMapImmutableMap

就我而言,该API是:/api/static_pages/?q=A+B+C

我的解决方案:

第1步:

@GET("/api/static_pages")
    Call<String> getStaticPagesByType(@HeaderMap HashMap<String, Object> header,
                               @QueryMap(encoded=true) Map<String, String> filters);

第2步:当我要调用API时:

List<String> listTypes = new ArrayList<>();
listTypes.add("A");
listTypes.add("B");
listTypes.add("C");

StringBuilder typeString = new StringBuilder();

int listSize = listType.size();

for (int i = 0; i < listSize - 1; i++) {
    typeString.append(listType.get(i));
    if(i != listSize-2){
       typeString.append("+");
    }
}
// The key is here!
ImmutableMap<String, String> types = ImmutableMap.of("q", typeString.toString());
getRetrofitClient().getStaticPagesByType(yourHeader, types)

希望它对您的工作有所帮助。

快乐的编码。

答案 2 :(得分:0)

更好的想法是,提出发送图像的多部分请求

@Multipart
@POST("api/v2/user/email_register")
Observable<UpdateUserInfoPayload> register(@Part("_height") String height, @Part("_target") String target, @Part("_width") String width, @Part("imageFile") TypedFile file);

参考:https://futurestud.io/blog/retrofit-how-to-upload-files#introduction

无需在改造中添加/删除%3F,它将自动处理

答案 3 :(得分:0)

如果您需要传递包含路径和查询参数的动态URL字符串,则应使用@Url Retrofit @Url

@POST(
Observable<UpdateUserInfoPayload> register(
        @Header("x-device-id") String deviceId,
        @Body RequestBody requestBody,
        @Url String method
);

其中method = api/v2/user/email_register?_height=1184&_target=android/2&_width=768

然后,请求将如下所示:

https://api.example.com/api/v2/user/email_register?_height=1184&_target=android/2&_width=768