Загрузите файл, используя пары Multipart и JSON Key-значение с Retrofit2 - PullRequest
2 голосов
/ 27 февраля 2020

В настоящее время мы загружаем файлы (Видео, Аудио, Текст и т. Д. c ..), конвертируя String bytes в простое JSON, включая некоторые другие значения с их парами ключ-значение. Как показано ниже:

Некоторые значения заголовка:

{
    "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.

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Работает нормально для меня (это мой код, просто адаптируйте его к своей бизнес-логике c):

Интерфейс:

@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 ответа и запроса. Пинг мне, если нужна помощь.

0 голосов
/ 27 февраля 2020

Вы можете использовать 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);
...