使用 Retrofit2 使用 Multipart 和 JSON 键值对上传文件
Upload file using both Multipart and JSON Key value pairs with Retrofit2
目前我们正在加载文件(视频、音频、文本等),方法是将 String bytes
转换为简单的 JSON,包括一些其他值及其 Key-Value 对。如下所示:
一些 header 值:
{
"header": {
"geoDate": {
"point": {
"longitude": 77.56246948242188,
"latitude": 12.928763389587403
},
"date": "2020-02-25T18:26:00Z"
},
"version": "1.35.00.001",
"businessId": "178"
}
}
和文件信息:
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);
这里params.data
是字节的简单转换String bytes = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT);
它正在运行,但我们希望通过 Retrofit 将文件通过 MultiPart 发送到服务器来实现,这也将提高性能。但问题是在 JSON 结构中,服务器无法更改其程序,我们(应用程序)只需要做一些使用 Retrofit Multipart 发送文件的事情,包括其他值和键(inputData
还有)。
我正在寻找一种方法来做到这一点。我想知道我们是否也能够发送,服务器是否必须更改 API 结构的任何内容,比如当前它接受字节的字符串,我们将把它更改为 inputData
的文件.
您可以使用 VolleyMultipartRequest 上传带有文本的文件。
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);
适合我(这是我的代码,只需根据您的业务逻辑进行调整):
接口:
@Multipart
@POST("{projectName}/log")
Call<LogRp> uploadFile(
@Path("projectName") String project,
@PartMap Map<String, RequestBody> mp,
@Part MultipartBody.Part file
);
服务:
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))
);
}
然后简单地:
client.uploadFile(
project,
buildJsonPart(logRq),
buildFilePart(file, type)
)
LogRp 和 LogRq 是响应和请求 POJO。
如果需要帮助,请联系我。
目前我们正在加载文件(视频、音频、文本等),方法是将 String bytes
转换为简单的 JSON,包括一些其他值及其 Key-Value 对。如下所示:
一些 header 值:
{
"header": {
"geoDate": {
"point": {
"longitude": 77.56246948242188,
"latitude": 12.928763389587403
},
"date": "2020-02-25T18:26:00Z"
},
"version": "1.35.00.001",
"businessId": "178"
}
}
和文件信息:
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);
这里params.data
是字节的简单转换String bytes = Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT);
它正在运行,但我们希望通过 Retrofit 将文件通过 MultiPart 发送到服务器来实现,这也将提高性能。但问题是在 JSON 结构中,服务器无法更改其程序,我们(应用程序)只需要做一些使用 Retrofit Multipart 发送文件的事情,包括其他值和键(inputData
还有)。
我正在寻找一种方法来做到这一点。我想知道我们是否也能够发送,服务器是否必须更改 API 结构的任何内容,比如当前它接受字节的字符串,我们将把它更改为 inputData
的文件.
您可以使用 VolleyMultipartRequest 上传带有文本的文件。
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);
适合我(这是我的代码,只需根据您的业务逻辑进行调整):
接口:
@Multipart
@POST("{projectName}/log")
Call<LogRp> uploadFile(
@Path("projectName") String project,
@PartMap Map<String, RequestBody> mp,
@Part MultipartBody.Part file
);
服务:
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))
);
}
然后简单地:
client.uploadFile(
project,
buildJsonPart(logRq),
buildFilePart(file, type)
)
LogRp 和 LogRq 是响应和请求 POJO。 如果需要帮助,请联系我。