I'm trying to send a picture to a server. My URL contains some parameters about my phone:
api/v2/user/email_register%3F_height=1184&_target=android/2&_width=768
and this is the working variant:
api/v2/user/email_register?_height=1184&_target=android/2&_width=768
(without irritation %3? code)
Also, I'm trying to pass my picture inside @Body:
@POST("/{url}")
Observable<UpdateUserInfoPayload> register(
@Header("x-device-id") String deviceId,
@Body RequestBody requestBody,
@Path(value = "url", encoded = true) String method
);
Creating it with 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();
}
That is why I'm unable to use for example:
@FieldMap Map<String, String> params
to pass my parameters there, because @FieldMap requires @FormUrlEncoded while I'm unable to make @Body request with @FormUrlEncoded.
1)How to remove %3F from my URL String? (outside retrofit everythin is fine!)
2)Is there any easy way to send a picture?
UPD: <-- 403 Forbidden https://api.example.com/api/v2/user/5984/validate_password when I use @Field annotation:
@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
);
Everything works when I use it like that:
@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
);
I want either to remove %3F or learn how to use Field in POST request without getting FORBIDDEN
The question mark ("?", ASCII 3F hex) is used to delimit the boundary between the URI of a queryable object, and a set of words used to express a query on that object. When this form is used, the combined URI stands for the object which results from the query being applied to the original object.
In a URL, the question mark (“?”) divides the address of an object and the set of words used in the query.
It's the query, or sometimes the query string.
Retrofit won't let you put the query string in the path. Take a look at @QueryMap instead, which is designed for this.
As refs: https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/QueryMap.html
I use @QueryMap
and ImmutableMap
.
In my case, the API is: /api/static_pages/?q=A+B+C
My solution:
Step 1:
@GET("/api/static_pages")
Call<String> getStaticPagesByType(@HeaderMap HashMap<String, Object> header,
@QueryMap(encoded=true) Map<String, String> filters);
Step 2: When I want to call 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)
Hope it help your work.
Happy coding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With