Currently we are uoloading files (Video, Audio, Text etc..) by converting String bytes
with simple JSON including some other values with their Key-Value pairs. Just like below:
Some header values:
{
"header": {
"geoDate": {
"point": {
"longitude": 77.56246948242188,
"latitude": 12.928763389587403
},
"date": "2020-02-25T18:26:00Z"
},
"version": "1.35.00.001",
"businessId": "178"
}
}
and files info:
JSONObject data = new JSONObject();
data.put("name", params.name);
data.put("mimeType", params.mimeType);
data.put("fileSize", params.fileSize);
data.put("inputData", params.data);
requestJSON.put("data", data);
Here params.data
is a simple conversion of bytes String bytes = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT);
It's working but we want to do it through Retrofit by sending the files through MultiPart to the server and which will improve the performance as well. But the problem is as it was in the JSON structure, the server can't change its program and we (app) only have to do something which sends the file using Retrofit Multipart including other values and keys(inputData
also).
I am searching for a way to do that. And I am wondering if we are able to send also, is the server has to change anything for the API structure like currently its accepting String for the bytes and we are going to change it to file for inputData
.
Works fine for me (it's my code, just adapt it to your business logic):
Interface:
@Multipart
@POST("{projectName}/log")
Call<LogRp> uploadFile(
@Path("projectName") String project,
@PartMap Map<String, RequestBody> mp,
@Part MultipartBody.Part file
);
Service:
private MultipartBody.Part buildFilePart(File file, FileType type) {
return MultipartBody.Part.createFormData("file", file.getName(),
RequestBody.create(MediaType.parse(type.value.get()), file));
}
private Map<String, RequestBody> buildJsonPart(LogRq logRq) throws JsonProcessingException {
return Collections.singletonMap("json_request_part", RequestBody.create(
MediaType.parse("application/json"),
new ObjectMapper().writeValueAsString(logRq))
);
}
And then simply:
client.uploadFile(
project,
buildJsonPart(logRq),
buildFilePart(file, type)
)
LogRp and LogRq are Response and Request POJOs.
ping me if help needed.
You can use VolleyMultipartRequest to upload File with text.
VolleyMultipartRequest multipartRequest = new VolleyMultipartRequest(Request.Method.PUT, url, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
String resultResponse = new String(response.data);
try {
JSONObject result = new JSONObject(resultResponse);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
String errorMessage = "Unknown error";
if (networkResponse == null) {
if (error.getClass().equals(TimeoutError.class)) {
errorMessage = "Request timeout";
} else if (error.getClass().equals(NoConnectionError.class)) {
errorMessage = "Failed to connect server";
}
} else {
String result = new String(networkResponse.data);
try {
JSONObject response = new JSONObject(result);
String status = response.getString("status");
String message = response.getString("message");
Log.e("Error Status", status);
Log.e("Error Message", message);
if (networkResponse.statusCode == 404) {
errorMessage = "Resource not found";
} else if (networkResponse.statusCode == 401) {
errorMessage = message + " Please login again";
} else if (networkResponse.statusCode == 400) {
errorMessage = message + " Check your inputs";
} else if (networkResponse.statusCode == 500) {
errorMessage = message + " Something is getting wrong";
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Log.i("Error", errorMessage);
error.printStackTrace();
}
}) {
@Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("Some_text", "text");
return params;
}
@Override
protected Map<String, DataPart> getByteData() {
Map<String, DataPart> params = new HashMap<>();
// file name could found file base or direct access from real path
// for now just get bitmap data from ImageView
params.put("pofile_pic", new DataPart("file_avatar.jpg", getFileDataFromDrawable(bitmap), "image/jpeg"));
return params;
}
};
VolleySingleton.getInstance(getActivity()).addToRequestQueue(multipartRequest);