Upload file using both Multipart and JSON Key valu

2020-03-07 06:02发布

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.

2条回答
狗以群分
2楼-- · 2020-03-07 06:39

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);
查看更多
【Aperson】
3楼-- · 2020-03-07 06:57

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.

查看更多
登录 后发表回答