Android

Why does PDF is not able to upload in PHP API for Android Pie, Q and R using Retrofit 2 in Android/Java? [Not solved]

Почему PDF не может быть загружен в PHP API для Android Pie, Q и R с использованием Retrofit 2 в Android / Java? [Не решено]

Я попытался загрузить PDF-файл [Не изображение] в PHP API с Android, и я получаю 400 с этим исключением:

{"head":{"StatusValue":400,"StatusText":"Failed"},"body":{"Error":"Missing required property fileId"}}

Я получаю 200 код запроса, когда я делаю в Postman:

введите описание изображения здесь

Теперь код Android:

    @Multipart
@POST("eligibity/auth/attachment/upload/add")
Call<ResponseBody> uploadFile(@Part MultipartBody.Part file, @Part("fileName") RequestBody name, @Part("body") JSONObject body);


private void uploadPDF(String path) {

String pdfname = String.valueOf(Calendar.getInstance().getTimeInMillis());

File file = new File(path);
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData("fileName", file.getName(), requestBody);
RequestBody filename = RequestBody.create(MediaType.parse("text/plain"), pdfname);

try {
JSONObject sJsonAttachment = new JSONObject();
JSONObject body = new JSONObject();
sJsonAttachment.put("appointmentId", AdapterCollections.clsClaimDiscussionList.get(position).appointment_id);
sJsonAttachment.put("createdBy", Integer.parseInt(preferenceManager.getUserId()));
sJsonAttachment.put("customerId", Integer.parseInt(preferenceManager.getCustomerId()));
sJsonAttachment.put("encounterId", AdapterCollections.clsClaimDiscussionList.get(position).encounter_id);
sJsonAttachment.put("expiryDate", Utility.getCurrentDate("MM-DD-YY"));
sJsonAttachment.put("fbType", 4);
sJsonAttachment.put("fileId", 0);
sJsonAttachment.put("fileName", "name");
sJsonAttachment.put("insTpaPatId", 0);
sJsonAttachment.put("isActive", 1);
sJsonAttachment.put("messageId", AdapterCollections.clsClaimDiscussionList.get(position).log_messages.get(position).log_id);
sJsonAttachment.put("patientId", AdapterCollections.clsClaimDiscussionList.get(position).patient_id);
sJsonAttachment.put("recType", "");
sJsonAttachment.put("reportDate", Utility.getCurrentDate("DD-MM-YYYY"));
sJsonAttachment.put("siteId", Integer.parseInt(preferenceManager.getSiteId()));
sJsonAttachment.put("type", 4);
sJsonAttachment.put("uploadDate", Utility.getCurrentDate("MMDDYY"));

// body.put("body", sJsonAttachment);

ApiCall apiCall = RetrofitService.createService(SCMS_BASE_URL, ApiCall.class);
assert apiCall != null;
apiCall.uploadFile(fileToUpload, filename, sJsonAttachment).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NotNull Call<ResponseBody> call, @NotNull Response<ResponseBody> response) {
try {
showLog("STATUS: " + response.code());
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void onFailure(@NotNull Call<ResponseBody> call, @NotNull Throwable t) {
showLog("FAILED: "+ t.getMessage());
}
});
} catch (Exception e) {
e.printStackTrace();
}


}

Я знаю, что делаю где-то небольшие ошибки, но не могу это заметить.

Если я использовал part, то эта ошибка: отсутствует требуемое свойство fileId, а если я использую query, то эта ошибка: должно быть object.

Обновить

Относительно пути:

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="/storage/emulated/0" path="."/>
</paths>

Намерение открыть PDF chooser:

 private void fileDialog() {
Intent intent = new Intent().setType("application/pdf").setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

startActivityForResult(Intent.createChooser(intent, "Select PDF file"), 123);
}

Я следовал этому https://javalang.ru/a/62830720/12630878 ответ на getPath, но я НЕ получаю path должным образом.

Более высокая версия означает: с 28 по 30

URI более высокой версии: URI: content://com.android.providers.media.documents /документ/document%3A31

ИЗ НЕДАВНИХ, если я выберу PDF, курсор возвращает null:

 if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}

ИЗ ЗАГРУЗОК, если я выберу PDF, то в этой строке появится исключение NumberFormatException:
URI: content://com.android.providers.downloads.documents/document/msf%3A27

Исключение: java.lang.NumberFormatException: Для входной строки: "msf: 27"

СТРОКА НЕТ: Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));

Класс FileUtils: https://drive.google.com/file/d/1S5-Sdp_CCSXXsOsZxwuhv0F5_CtH2EQO/view?usp=sharing

Найдите этот метод, где я получаю Path:

public static File getFile(Context context, Uri uri) {
if (uri != null) {
String path = getPathForAllVersion(context, uri);
// String path = getFilePathFromURI(context, uri);
showLog("isPATH: " + path);
if (checkNull(path) && isLocal(path)) {
return new File(path);
}
}
return null;
}
Переведено автоматически
Ответ 1

Ваш api принимает только два параметра, но вы передали три параметра, поэтому вы получаете ошибку.

итак, метод API должен быть

@Multipart
@POST("eligibity/auth/attachment/upload/add")
Call<ResponseBody> uploadFile(
@Part("body") RequestBody description,
@Part MultipartBody.Part file
)
;

И обновите свойuploadPDF(), как показано ниже

    private void uploadPDF(String path) {

//json data
JSONObject sJsonAttachment = new JSONObject();
JSONObject body = new JSONObject();
sJsonAttachment.put("appointmentId", AdapterCollections.clsClaimDiscussionList.get(position).appointment_id);
sJsonAttachment.put("createdBy", Integer.parseInt(preferenceManager.getUserId()));
sJsonAttachment.put("customerId", Integer.parseInt(preferenceManager.getCustomerId()));
sJsonAttachment.put("encounterId", AdapterCollections.clsClaimDiscussionList.get(position).encounter_id);
sJsonAttachment.put("expiryDate", Utility.getCurrentDate("MM-DD-YY"));
sJsonAttachment.put("fbType", 4);
sJsonAttachment.put("fileId", 0);
sJsonAttachment.put("fileName", "name");
sJsonAttachment.put("insTpaPatId", 0);
sJsonAttachment.put("isActive", 1);
sJsonAttachment.put("messageId", AdapterCollections.clsClaimDiscussionList.get(position).log_messages.get(position).log_id);
sJsonAttachment.put("patientId", AdapterCollections.clsClaimDiscussionList.get(position).patient_id);
sJsonAttachment.put("recType", "");
sJsonAttachment.put("reportDate", Utility.getCurrentDate("DD-MM-YYYY"));
sJsonAttachment.put("siteId", Integer.parseInt(preferenceManager.getSiteId()));
sJsonAttachment.put("type", 4);
sJsonAttachment.put("uploadDate", Utility.getCurrentDate("MMDDYY"));




// create RequestBody instance from file
File file=new File(path);
RequestBody requestFile =
RequestBody.create(
MediaType.parse(Files.probeContentType(file.toPath()))),
file
);

// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part fileBody =
MultipartBody.Part.createFormData("fileName", file.getName(), requestFile);

// add another part within the multipart request
RequestBody bodyJsonAttachment =
RequestBody.create(
okhttp3.MultipartBody.FORM, sJsonAttachment.toString());


ApiCall apiCall = RetrofitService.createService(SCMS_BASE_URL, ApiCall.class);
assert apiCall != null;
apiCall.uploadFile(fileBody, bodyJsonAttachment).enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NotNull Call<ResponseBody> call, @NotNull Response<ResponseBody> response) {
try {
showLog("STATUS: " + response.code());
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void onFailure(@NotNull Call<ResponseBody> call, @NotNull Throwable t) {
showLog("FAILED: "+ t.getMessage());
}
});

}

Примечание : если вы получаете предупреждение об ошибке mime-типа, обновите его

Ответ 2

Если вы используете multipart, передайте все поля в Multipart точно так же.

Объявите метод в интерфейсе Api точно так же. Только одно поле MultipartBody.

@Multipart
@POST("eligibity/auth/attachment/upload/add")
Call<ResponseBody> uploadFile(@Body MultipartBody body);

Создать MultipartBody.Builder добавьте в него свой и ваше поле.

    MultipartBody.Builder requestBodyBuilde = MultipartBody.Builder().setType(MultipartBody.FORM);

//adding image in multipart
File file = File(selected_file_path);
RequestBody fileBody = ProgressRequestBody(file, this);
requestBodyBuilde.addFormDataPart("fileName", file.name, fileBody);

//add your other field just like this
requestBodyBuilde.addFormDataPart("body", sJsonAttachment );



ApiCall apiCall = RetrofitService.createService(SCMS_BASE_URL, ApiCall.class);
assert apiCall != null;
//Note here we will pass only one parameter that is multipartBody
apiCall.uploadFile(requestBodyBuilde.build()).enqueue(new
Callback<ResponseBody>() {
@Override
public void onResponse(@NotNull Call<ResponseBody> call, @NotNull Response<ResponseBody> response) {
try {
showLog("STATUS: " + response.code());
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void onFailure(@NotNull Call<ResponseBody> call, @NotNull Throwable t) {
showLog("FAILED: "+ t.getMessage());
}
});
} catch (Exception e) {
e.printStackTrace();
}
java android