2017-06-30 5 views
6

Retrofit2経由でMultipart 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

"@Part"の代わりに "@PartMap"というアノテーションを使用すると、問題が解決しました。 – kike

+0

同じ問題を抱えている人々がコードを実行できるように、call.enqueue()をこの回答に追加してください。 – kike

+1

@kike私は自分の答えを変更し、ファイルのほかに文字列を送る方法も追加しました。 –

2

録音をアップロードしようとしたときにこの問題が発生しました。私はファイルをアップロードするWebサービスを呼び出す前に、録音プロセスを停止して解決しました。

関連する問題