2017-06-30 2 views
6

Ich versuche, eine Multipart-POST-Anfrage durch Retrofit2 zu machen, wo ich eine benutzerdefinierte Datei in die API hochlade.Nachrüstung. java.net.ProtocolException: erwartet * Bytes aber erhalten *

Es schlägt fehl, zufällig mit dieser Ausnahme:

W/System.err: java.net.ProtocolException: expected 154 bytes but received 634 

Hat jemand könnte auf sie etwas Licht bringen?

Dies ist mein Code in der Schnittstelle:

@Multipart 
@POST("recordings/{id}/{rec_id}/") 
Call<ResponseBody> uploadRecording(@Path("id") String id, @Path("rec_id") String rec_id, @Part MultipartBody.Part bleFile); 

im Konstruktor:

public ApiConnectionManager(Context con){ 
    Gson gson = new GsonBuilder() 
      .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") 
      .create(); 

    OkHttpClient.Builder client = new OkHttpClient.Builder(); 
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); 
    loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
    client.addInterceptor(loggingInterceptor); 

    Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl(con.getResources().getString(R.string.api_url)) // API url is hidden 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .client(client.build()) 
      .build(); 

    this.companyAPI = retrofit.create(CompanyAPI.class); 
} 

und im Upload-Methode:

private void uploadFile(String id, final File bleFile) { 
    MediaType MEDIA_TYPE = MediaType.parse("multipart/mixed"); 
    RequestBody requestBody = RequestBody.create(MEDIA_TYPE,bleFile); 
    MultipartBody.Part partFile = MultipartBody.Part.createFormData("file", bleFile.getName(), requestBody); 
    String recordingId = bleFile.getName().replace(".BLE",""); 
    Call<ResponseBody> call = companyAPI.uploadRecording(id, recordingId, partFile); 
    call.enqueue(new Callback<ResponseBody>() { 
     @Override 
     public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 
      Log.d(TAG+"-Upload "+bleFile.getName(),response.message()); 
     } 

     @Override 
     public void onFailure(Call<ResponseBody> call, Throwable t) { 
      Log.d(TAG,"FAILED"); 
      t.printStackTrace(); 
     } 
    }); 
} 

Antwort

1

Nach einer während des Studiums das Problem, das ich, dass der Inhalt der Datei realisiert habe immer veränderte (wie es die Ausgabe eines Sensors ist).

Es bedeutet, dass die Datei, die für den HEAD und die Datei für den BODY überprüft wird, möglicherweise nicht die gleichen Daten (daher unterschiedliche Länge) enthält, die die Abweichung verursacht.

Ich löste dieses creating a copy der Datei und sendete es (die Kopie) anstelle der ursprünglichen Datei.

1

Hier ist, was ich für alle verwenden meine Anfragen und haben überhaupt keine Probleme. Lass es mich wissen, wenn es nicht für dich funktioniert. Ich nehme an, POST-Name für Ihre Datei ist "Datei".

Im Protokoll:

@Multipart 
@POST 
Call<ResponseBody> request(
     @Url String url, // Request URL 
     @PartMap Map<String, String> vars, // POST Strings 
     @PartMap Map<String, RequestBody> files // POST Files 
); 

einen Anruf Construct:

Map<String, String> vars = new HashMap<>(); 
Map<String, RequestBody> files = new HashMap<>(); 

/** Put a string **/ 

vars.put("name", "value"); 

/** Put a file **/ 

String key = String.format(Locale.US, "file\"; filename=\"%s", file.getName()); 
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file); 
files.put(key, requestBody); 

/** Construct the call **/ 

Call<ResponseBody> call = mProtocol.request(url, vars, files); 

call.enqueue(new Callback<ResponseBody>() { 
     @Override 
     public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 
      Log.d("Debug", response.body().string()); 
     } 

     @Override 
     public void onFailure(Call<ResponseBody> call, Throwable t) { 
      if (call.isCanceled()) Log.d("Debug", "Call Canceled"); 
      else Log.d("Debug", "Call Failed: " + t.toString()); 
     } 
}); 

PS: Sie können dieses Stück Code verwenden, um mehrere Dateien zu laden, da es eine Karte von Dateien und nicht als akzeptiert einzelne Datei.

PS # 2: Aufgrund einiger Probleme, die ich mit dieser Methode hatte, musste ich den folgenden Code hinzufügen, um sicherzustellen, dass es nie Null oder leere Karte sendet.

if (vars == null) { 
    vars = new HashMap<>(); 
    vars.put("01110011", "01101101"); // put whatever you want 
} 
if (files == null) files = new HashMap<>(); 
+0

mit der Annotation "@PartMap" anstelle von "@Part" löste das Problem. – kike

+0

Könnten Sie bitte call.enqueue() zu dieser Antwort hinzufügen, damit die Leute mit dem gleichen Problem einen funktionierenden Code haben? – kike

+1

@kike Ich habe meine Antwort geändert und hinzugefügt, wie man Strings neben Dateien sendet. –

2

Ich hatte dieses Problem, als ich versuchte, eine Aufnahme hochzuladen. Ich habe es gelöst, indem ich den Aufnahmeprozess gestoppt habe, bevor ich den Webservice anrief, um die Datei hochzuladen.

objMediaRecorder.stop(); 
objMediaRecorder.release(); 
objMediaRecorder = null; 
Verwandte Themen