2017-06-30 38 views
6

我想通過Retrofit2做一個多部分POST請求,在那裏我上傳到一個自定義文件的API。改造。 java.net.ProtocolException:期望的*字節,但收到*

它隨機失敗,出現此異常:

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

有誰可以把一些光就可以了?

這是我在接口代碼:

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

在構造函數中:

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); 
} 

,並在上傳方法:

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(); 
     } 
    }); 
} 

回答

1

了一段時間學習我已經意識到這個問題,該文件的內容總是不斷變化的(因爲它是一個傳感器的輸出)之後。

這意味着檢查HEAD的文件和BODY的文件可能不包含相同的數據(因此長度不同),從而導致不匹配。

我解決了這個文件的creating a copy併發送它(副本),而不是原始文件。

1

以下是我使用的所有我的要求並沒有任何問題。讓我知道,如果它不適合你。我假設你的文件的POST名稱是「文件」。

在協議:

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

構建一個電話:

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:你可以使用這段代碼上傳多個文件,因爲它接受映射一個文件,而不是單個文件。

PS#2:由於我用這種方法遇到了幾個問題,我不得不添加下面的代碼以確保它永遠不會發送空映射或空映射。

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

使用註解「@PartMap」而不是「@Part」解決了這個問題。 – kike

+0

請問您可以將call.enqueue()添加到此答案中,以便具有相同問題的人員可以擁有一段代碼? – kike

+1

@kike我改變了我的答案,並且還添加了如何發送字符串以外的文件。 –

2

我在試圖上傳錄音時遇到了這個問題。我通過在調用Web服務上傳文件之前停止錄製過程來解決這個問題。

objMediaRecorder.stop(); 
objMediaRecorder.release(); 
objMediaRecorder = null; 
相關問題