Как правильно управлять запросом Retrofit POST?
На самом деле я пытаюсь опубликовать текстовый файл на моем сервере, и я смогу обработать ошибку, когда я отправил файл, но я не получил ответ (В случае, если файл был отправлен, сеть не работает поэтому сервер получил файл, но устройство его не знает)
Потому что сейчас я получаю проблему, потому что, если я не получаю ответ, когда устройство возвращается в онлайн, оно отправляет снова тот же файл, и я бы это предотвратил.
Кажется, что это скрытая попытка отправить файл при сбое подключения или что-то в этом роде.
Вот мой метод, который я использую onClick для отправки файла:
public void sendPost() {
@SuppressLint({"SdCardPath", "DefaultLocale"}) final File file = new File("/data/data/com.example.igardini.visualposmobile/files/"+String.format("%03d", Integer.valueOf(nTerminalino))+"_"+nTavoli.getText().toString()+".txt");
final MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
final RequestBody fbody = RequestBody.create(MediaType.parse("text/*"), file);
builder.addFormDataPart(String.format("%03d", Integer.valueOf(nTerminalino))+"_"+nTavoli.getText().toString(), file.getName(),fbody);
final MultipartBody requestBody = builder.build();
final APIService apiService = ApiUtils.getAPIService(ipCASSA);
final Call<Void> calls = apiService.savePost(requestBody);
calls.enqueue(new Callback<Void>() {
@Override
public void onResponse(@NonNull Call<Void> call, @NonNull Response<Void> response) {
if (response.isSuccessful()) {
Log.i("RESPONSE: ", response.toString());
Print();
dialogLoading.dismiss();
Runtime.getRuntime().gc();
// checkFile task = new checkFile();
// task.execute();
}else {
Toast.makeText(pterm.this,"ERRORE",Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(@NonNull Call<Void> call, @NonNull Throwable t) {
if(t instanceof IOException) {
Log.e("TAG", t.toString());
MediaPlayer mpFound = MediaPlayer.create(pterm.this, R.raw.errorsound);
mpFound.start();
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (v.hasVibrator()) {
v.vibrate(6000);
}
new GlideToast.makeToast(pterm.this, "CONNESSIONE FALLITA!", GlideToast.LENGTHLONG, GlideToast.FAILTOAST).show();
dialogLoading.dismiss();
}
}
});
}
Пока вот мои другие полезные занятия:
class ApiUtils {
private ApiUtils() {}
static APIService getAPIService(String ipCASSA) {
String BASE_URL = "http://"+ipCASSA+"/web/";
final OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10000, TimeUnit.MILLISECONDS)
.writeTimeout(10000, TimeUnit.MILLISECONDS)
.readTimeout(10000, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(false)
.build();
return RetrofitClient.getClient(BASE_URL,okHttpClient).create(APIService.class);
}
}
public interface APIService {
@POST("CART=PTERM")
Call<Void> savePost(@Body RequestBody text);
}
class RetrofitClient {
private static Retrofit retrofit = null;
static Retrofit getClient(String baseUrl, OkHttpClient okHttpClient) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
1 ответ
В этом случае я бы добавил в файл какой-то случайный идентификатор, сгенерированный устройством, и отправил бы его вместе с запросом.
На стороне сервера я бы изменил логику, чтобы сначала попытаться найти файл в БД с использованием этого идентификатора, если его нет, сохранить его и вернуть состояние ОК вместе с, возможно, идентификатором стороны сервера (может пригодиться позже).
Если есть файл с идентификатором, предоставленным по запросу, просто верните идентификатор стороны сервера со статусом 200 - таким образом, вы не будете хранить его дважды.
Вы даже можете пойти дальше - если у вас нестабильное соединение (кажется, что это из описания), вы можете даже сделать отдельный вызов REST, чтобы проверить, находится ли файл на стороне сервера по сгенерированному идентификатору или контрольной сумме, и если нет, то начать отправлять его - это будет безопасный Bandwitch.
Это не обязательно должен быть сгенерированный идентификатор - это может быть контрольная сумма файла, например. Все, что проще для вас.
Для генерации идентификатора вы можете использовать UUID Android https://developer.android.com/reference/java/util/UUID
Для контрольной суммы проверьте этот ответ: Как создать контрольную сумму MD5 для файла в Android?
Кстати, я бы не стал делать 10-секундный лимит времени - это слишком много, и пользовательский опыт будет ужасным